diff --git a/mingw-w64-tools/widl/src/client.c b/mingw-w64-tools/widl/src/client.c
index a3b2bbb6..d27c6cad 100644
--- a/mingw-w64-tools/widl/src/client.c
+++ b/mingw-w64-tools/widl/src/client.c
@@ -20,7 +20,7 @@
 
 #include "config.h"
 #include "wine/port.h"
- 
+
 #include <stdio.h>
 #include <stdlib.h>
 #ifdef HAVE_UNISTD_H
@@ -34,7 +34,7 @@
 #include "parser.h"
 #include "header.h"
 
-#include "widltypes.h"
+#include "typetree.h"
 #include "typegen.h"
 #include "expr.h"
 
@@ -52,12 +52,13 @@ static void print_client( const char *format, ... )
 
 static void write_client_func_decl( const type_t *iface, const var_t *func )
 {
-    const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV);
-    const var_list_t *args = type_get_function_args(func->type);
-    type_t *rettype = type_function_get_rettype(func->type);
+    const char *callconv = get_attrp(func->declspec.type->attrs, ATTR_CALLCONV);
+    const var_list_t *args = type_function_get_args(func->declspec.type);
+    const decl_spec_t *retdeclspec = type_function_get_retdeclspec(func->declspec.type);
 
     if (!callconv) callconv = "__cdecl";
-    write_type_decl_left(client, rettype);
+    write_declspec_decl_left(client, retdeclspec);
+    if (func->declspec.funcspecifier == FUNCTION_SPECIFIER_INLINE) fprintf(client, " inline");
     fprintf(client, " %s ", callconv);
     fprintf(client, "%s%s(\n", prefix_client, get_name(func));
     indent++;
@@ -74,9 +75,9 @@ static void write_function_stub( const type_t *iface, const var_t *func,
 {
     unsigned char explicit_fc, implicit_fc;
     int has_full_pointer = is_full_pointer_function(func);
-    var_t *retval = type_function_get_retval(func->type);
+    var_t *retval = type_function_get_retval(func->declspec.type);
     const var_t *handle_var = get_func_handle_var( iface, func, &explicit_fc, &implicit_fc );
-    int has_ret = !is_void(retval->type);
+    int has_ret = !is_void(retval->declspec.type);
 
     if (is_interpreted_func( iface, func ))
     {
@@ -97,7 +98,7 @@ static void write_function_stub( const type_t *iface, const var_t *func,
         print_client("RPC_BINDING_HANDLE _Handle;\n");
     }
 
-    if (has_ret && decl_indirect(retval->type))
+    if (has_ret && decl_indirect(retval->declspec.type))
     {
         print_client("void *_p_%s;\n", retval->name);
     }
@@ -136,7 +137,7 @@ static void write_function_stub( const type_t *iface, const var_t *func,
     if (has_ret)
     {
         print_client("%s", "");
-        write_type_decl(client, retval->type, retval->name);
+        write_declspec_decl(client, &retval->declspec, retval->name);
         fprintf(client, ";\n");
     }
     print_client("RPC_MESSAGE _RpcMessage;\n");
@@ -147,7 +148,7 @@ static void write_function_stub( const type_t *iface, const var_t *func,
         if (explicit_fc == FC_BIND_GENERIC)
             print_client("__frame->%s = %s;\n", handle_var->name, handle_var->name );
     }
-    if (has_ret && decl_indirect(retval->type))
+    if (has_ret && decl_indirect(retval->declspec.type))
     {
         print_client("__frame->_p_%s = &%s;\n", retval->name, retval->name);
     }
@@ -194,7 +195,7 @@ static void write_function_stub( const type_t *iface, const var_t *func,
         /* if the context_handle attribute appears in the chain of types
          * without pointers being followed, then the context handle must
          * be direct, otherwise it is a pointer */
-        int is_ch_ptr = !is_aliaschain_attr(handle_var->type, ATTR_CONTEXTHANDLE);
+        int is_ch_ptr = !is_aliaschain_attr(handle_var->declspec.type, ATTR_CONTEXTHANDLE);
         print_client("if (%s%s != 0)\n", is_ch_ptr ? "*" : "", handle_var->name);
         indent++;
         print_client("__frame->_Handle = NDRCContextBinding(%s%s);\n",
@@ -257,9 +258,9 @@ static void write_function_stub( const type_t *iface, const var_t *func,
     /* unmarshal return value */
     if (has_ret)
     {
-        if (decl_indirect(retval->type))
+        if (decl_indirect(retval->declspec.type))
             print_client("MIDL_memset(&%s, 0, sizeof(%s));\n", retval->name, retval->name);
-        else if (is_ptr(retval->type) || is_array(retval->type))
+        else if (is_ptr(retval->declspec.type) || is_array(retval->declspec.type))
             print_client("%s = 0;\n", retval->name);
         write_remoting_arguments(client, indent, func, "", PASS_RETURN, PHASE_UNMARSHAL);
     }
@@ -291,7 +292,7 @@ static void write_serialize_function(FILE *file, const type_t *type, const type_
                                      const char *func_name, const char *ret_type)
 {
     enum stub_mode mode = get_stub_mode();
-    static int emited_pickling_info;
+    static int emitted_pickling_info;
 
     if (iface && !type->typestring_offset)
     {
@@ -301,7 +302,7 @@ static void write_serialize_function(FILE *file, const type_t *type, const type_
         return;
     }
 
-    if (!emited_pickling_info && iface && mode != MODE_Os)
+    if (!emitted_pickling_info && iface && mode != MODE_Os)
     {
         fprintf(file, "static const MIDL_TYPE_PICKLING_INFO __MIDL_TypePicklingInfo =\n");
         fprintf(file, "{\n");
@@ -312,7 +313,7 @@ static void write_serialize_function(FILE *file, const type_t *type, const type_
         fprintf(file, "    0\n");
         fprintf(file, "};\n");
         fprintf(file, "\n");
-        emited_pickling_info = 1;
+        emitted_pickling_info = 1;
     }
 
     /* FIXME: Assuming explicit handle */
@@ -365,8 +366,8 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset)
         case STMT_DECLARATION:
         {
             const var_t *func = stmt->u.var;
-            if (stmt->u.var->stgclass != STG_NONE
-                || type_get_type_detect_alias(stmt->u.var->type) != TYPE_FUNCTION)
+            if (stmt->u.var->declspec.stgclass != STG_NONE
+                || type_get_type_detect_alias(stmt->u.var->declspec.type) != TYPE_FUNCTION)
                 continue;
             write_function_stub( iface, func, method_count++, *proc_offset );
             *proc_offset += get_size_procformatstring_func( iface, func );
@@ -425,7 +426,7 @@ static void write_stubdescriptor(type_t *iface, int expr_eval_routines)
     print_client("1, /* -error bounds_check flag */\n");
     print_client("0x%x, /* Ndr library version */\n", get_stub_mode() == MODE_Oif ? 0x50002 : 0x10001);
     print_client("0,\n");
-    print_client("0x50100a4, /* MIDL Version 5.1.164 */\n");
+    print_client("0x50200ca, /* MIDL Version 5.2.202 */\n");
     print_client("0,\n");
     print_client("%s,\n", list_empty(&user_type_list) ? "0" : "UserMarshalRoutines");
     print_client("0,  /* notify & notify_flag routine table */\n");
@@ -488,7 +489,7 @@ static void write_implicithandledecl(type_t *iface)
 
     if (implicit_handle)
     {
-        write_type_decl( client, implicit_handle->type, implicit_handle->name );
+        write_declspec_decl( client, &implicit_handle->declspec, implicit_handle->name );
         fprintf(client, ";\n\n");
     }
 }
@@ -532,8 +533,8 @@ static void write_client_ifaces(const statement_list_t *stmts, int expr_eval_rou
 
             LIST_FOR_EACH_ENTRY(stmt2, type_iface_get_stmts(iface), const statement_t, entry)
             {
-                if (stmt2->type == STMT_DECLARATION && stmt2->u.var->stgclass == STG_NONE &&
-                    type_get_type_detect_alias(stmt2->u.var->type) == TYPE_FUNCTION)
+                if (stmt2->type == STMT_DECLARATION && stmt2->u.var->declspec.stgclass == STG_NONE &&
+                    type_get_type_detect_alias(stmt2->u.var->declspec.type) == TYPE_FUNCTION)
                 {
                     needs_stub = 1;
                     break;
@@ -627,26 +628,6 @@ void write_client(const statement_list_t *stmts)
     if (!client)
         return;
 
-    if (do_win32 && do_win64)
-    {
-        fprintf(client, "#ifndef _WIN64\n\n");
-        pointer_size = 4;
-        write_client_routines( stmts );
-        fprintf(client, "\n#else /* _WIN64 */\n\n");
-        pointer_size = 8;
-        write_client_routines( stmts );
-        fprintf(client, "\n#endif /* _WIN64 */\n");
-    }
-    else if (do_win32)
-    {
-        pointer_size = 4;
-        write_client_routines( stmts );
-    }
-    else if (do_win64)
-    {
-        pointer_size = 8;
-        write_client_routines( stmts );
-    }
-
+    write_client_routines( stmts );
     fclose(client);
 }
diff --git a/mingw-w64-tools/widl/src/expr.c b/mingw-w64-tools/widl/src/expr.c
index 2ed4aff6..2f075816 100644
--- a/mingw-w64-tools/widl/src/expr.c
+++ b/mingw-w64-tools/widl/src/expr.c
@@ -194,10 +194,10 @@ expr_t *make_exprt(enum expr_type type, var_t *var, expr_t *expr)
     expr_t *e;
     type_t *tref;
 
-    if (var->stgclass != STG_NONE && var->stgclass != STG_REGISTER)
+    if (var->declspec.stgclass != STG_NONE && var->declspec.stgclass != STG_REGISTER)
         error_loc("invalid storage class for type expression\n");
 
-    tref = var->type;
+    tref = var->declspec.type;
 
     e = xmalloc(sizeof(expr_t));
     e->type = type;
@@ -474,7 +474,7 @@ static type_t *find_identifier(const char *identifier, const type_t *cont_type,
     if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
         if (field->name && !strcmp(identifier, field->name))
         {
-            type = field->type;
+            type = field->declspec.type;
             *found_in_cont_type = 1;
             break;
         }
@@ -482,7 +482,7 @@ static type_t *find_identifier(const char *identifier, const type_t *cont_type,
     if (!type)
     {
         var_t *const_var = find_const(identifier, 0);
-        if (const_var) type = const_var->type;
+        if (const_var) type = const_var->declspec.type;
     }
 
     return type;
@@ -521,11 +521,11 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc
         break;
     case EXPR_STRLIT:
         result.is_temporary = TRUE;
-        result.type = type_new_pointer(FC_UP, type_new_int(TYPE_BASIC_CHAR, 0), NULL);
+        result.type = type_new_pointer(FC_UP, type_new_int(TYPE_BASIC_CHAR, 0));
         break;
     case EXPR_WSTRLIT:
         result.is_temporary = TRUE;
-        result.type = type_new_pointer(FC_UP, type_new_int(TYPE_BASIC_WCHAR, 0), NULL);
+        result.type = type_new_pointer(FC_UP, type_new_int(TYPE_BASIC_WCHAR, 0));
         break;
     case EXPR_CHARCONST:
         result.is_temporary = TRUE;
@@ -575,15 +575,15 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc
                            expr_loc->attr ? expr_loc->attr : "");
         result.is_variable = FALSE;
         result.is_temporary = TRUE;
-        result.type = type_new_pointer(FC_UP, result.type, NULL);
+        result.type = type_new_pointer(FC_UP, result.type);
         break;
     case EXPR_PPTR:
         result = resolve_expression(expr_loc, cont_type, e->ref);
         if (result.type && is_ptr(result.type))
-            result.type = type_pointer_get_ref(result.type);
+            result.type = type_pointer_get_ref_type(result.type);
         else if(result.type && is_array(result.type)
                             && type_array_is_decl_as_ptr(result.type))
-            result.type = type_array_get_element(result.type);
+            result.type = type_array_get_element_type(result.type);
         else
             error_loc_info(&expr_loc->v->loc_info, "dereference operator applied to non-pointer type in expression%s%s\n",
                            expr_loc->attr ? " for attribute " : "",
@@ -665,7 +665,7 @@ static struct expression_type resolve_expression(const struct expr_loc *expr_loc
         if (result.type && is_array(result.type))
         {
             struct expression_type index_result;
-            result.type = type_array_get_element(result.type);
+            result.type = type_array_get_element_type(result.type);
             index_result = resolve_expression(expr_loc, cont_type /* FIXME */, e->u.ext);
             if (!index_result.type || !is_integer_type(index_result.type))
                 error_loc_info(&expr_loc->v->loc_info, "array subscript not of integral type in expression%s%s\n",
diff --git a/mingw-w64-tools/widl/src/header.c b/mingw-w64-tools/widl/src/header.c
index defc7f85..d0d0dc4b 100644
--- a/mingw-w64-tools/widl/src/header.c
+++ b/mingw-w64-tools/widl/src/header.c
@@ -43,7 +43,7 @@ user_type_list_t user_type_list = LIST_INIT(user_type_list);
 context_handle_list_t context_handle_list = LIST_INIT(context_handle_list);
 generic_handle_list_t generic_handle_list = LIST_INIT(generic_handle_list);
 
-static void write_type_def_or_decl(FILE *f, type_t *t, int field, const char *name);
+static void write_type_v(FILE *h, const decl_spec_t *ds, int is_field, int declonly, const char *name);
 
 static void indent(FILE *h, int delta)
 {
@@ -69,15 +69,15 @@ int is_ptrchain_attr(const var_t *var, enum attr_type t)
         return 1;
     else
     {
-        type_t *type = var->type;
+        type_t *type = var->declspec.type;
         for (;;)
         {
             if (is_attr(type->attrs, t))
                 return 1;
             else if (type_is_alias(type))
-                type = type_alias_get_aliasee(type);
+                type = type_alias_get_aliasee_type(type);
             else if (is_ptr(type))
-                type = type_pointer_get_ref(type);
+                type = type_pointer_get_ref_type(type);
             else return 0;
         }
     }
@@ -91,7 +91,7 @@ int is_aliaschain_attr(const type_t *type, enum attr_type attr)
         if (is_attr(t->attrs, attr))
             return 1;
         else if (type_is_alias(t))
-            t = type_alias_get_aliasee(t);
+            t = type_alias_get_aliasee_type(t);
         else return 0;
     }
 }
@@ -204,9 +204,9 @@ static void write_fields(FILE *h, var_list_t *fields)
     if (!fields) return;
 
     LIST_FOR_EACH_ENTRY( v, fields, var_t, entry ) {
-        if (!v || !v->type) continue;
+        if (!v || !v->declspec.type) continue;
 
-        switch(type_get_type_detect_alias(v->type)) {
+        switch(type_get_type_detect_alias(v->declspec.type)) {
         case TYPE_STRUCT:
         case TYPE_ENCAPSULATED_UNION:
             nameless_struct_cnt++;
@@ -220,12 +220,12 @@ static void write_fields(FILE *h, var_list_t *fields)
     }
 
     LIST_FOR_EACH_ENTRY( v, fields, var_t, entry ) {
-        if (!v || !v->type) continue;
+        if (!v || !v->declspec.type) continue;
 
         indent(h, 0);
         name = v->name;
 
-        switch(type_get_type_detect_alias(v->type)) {
+        switch(type_get_type_detect_alias(v->declspec.type)) {
         case TYPE_STRUCT:
         case TYPE_ENCAPSULATED_UNION:
             if(!v->name) {
@@ -252,7 +252,7 @@ static void write_fields(FILE *h, var_list_t *fields)
         default:
             ;
         }
-        write_type_def_or_decl(h, v->type, TRUE, name);
+        write_type_v(h, &v->declspec, TRUE, v->declonly, name);
         fprintf(h, ";\n");
     }
 }
@@ -295,14 +295,21 @@ static void write_pointer_left(FILE *h, type_t *ref)
 }
 
 void write_type_left(FILE *h, type_t *t, enum name_type name_type, int declonly)
+{
+  decl_spec_t ds;
+  write_declspec_left(h, init_declspec(&ds, t), name_type, declonly);
+}
+
+void write_declspec_left(FILE* h, const decl_spec_t *ds, enum name_type name_type, int declonly)
 {
   const char *name;
+  type_t *t = ds->type;
 
   if (!h) return;
 
   name = type_get_name(t, name_type);
 
-  if (is_attr(t->attrs, ATTR_CONST) &&
+  if ((ds->typequalifier == TYPE_QUALIFIER_CONST) &&
       (type_is_alias(t) || !is_ptr(t)))
     fprintf(h, "const ");
 
@@ -310,7 +317,7 @@ void write_type_left(FILE *h, type_t *t, enum name_type name_type, int declonly)
   else {
     switch (type_get_type_detect_alias(t)) {
       case TYPE_ENUM:
-        if (!declonly && t->defined && !t->written) {
+        if (!declonly && type_is_defined(t) && !t->written) {
           if (name) fprintf(h, "enum %s {\n", name);
           else fprintf(h, "enum {\n");
           t->written = TRUE;
@@ -323,7 +330,7 @@ void write_type_left(FILE *h, type_t *t, enum name_type name_type, int declonly)
         break;
       case TYPE_STRUCT:
       case TYPE_ENCAPSULATED_UNION:
-        if (!declonly && t->defined && !t->written) {
+        if (!declonly && type_is_defined(t) && !t->written) {
           if (name) fprintf(h, "struct %s {\n", name);
           else fprintf(h, "struct {\n");
           t->written = TRUE;
@@ -338,7 +345,7 @@ void write_type_left(FILE *h, type_t *t, enum name_type name_type, int declonly)
         else fprintf(h, "struct %s", name ? name : "");
         break;
       case TYPE_UNION:
-        if (!declonly && t->defined && !t->written) {
+        if (!declonly && type_is_defined(t) && !t->written) {
           if (t->name) fprintf(h, "union %s {\n", t->name);
           else fprintf(h, "union {\n");
           t->written = TRUE;
@@ -351,9 +358,9 @@ void write_type_left(FILE *h, type_t *t, enum name_type name_type, int declonly)
         break;
       case TYPE_POINTER:
       {
-        write_type_left(h, type_pointer_get_ref(t), name_type, declonly);
-        write_pointer_left(h, type_pointer_get_ref(t));
-        if (is_attr(t->attrs, ATTR_CONST)) fprintf(h, "const ");
+        write_declspec_left(h, type_pointer_get_ref(t), name_type, declonly);
+        write_pointer_left(h, type_pointer_get_ref_type(t));
+        if (ds->typequalifier == TYPE_QUALIFIER_CONST) fprintf(h, "const ");
         break;
       }
       case TYPE_ARRAY:
@@ -361,9 +368,9 @@ void write_type_left(FILE *h, type_t *t, enum name_type name_type, int declonly)
           fprintf(h, "%s", t->name);
         else
         {
-          write_type_left(h, type_array_get_element(t), name_type, declonly);
+          write_declspec_left(h, type_array_get_element(t), name_type, declonly);
           if (type_array_is_decl_as_ptr(t))
-            write_pointer_left(h, type_array_get_element(t));
+            write_pointer_left(h, type_array_get_element_type(t));
         }
         break;
       case TYPE_BASIC:
@@ -443,7 +450,7 @@ void write_type_right(FILE *h, type_t *t, int is_field)
   {
   case TYPE_ARRAY:
   {
-    type_t *elem = type_array_get_element(t);
+    type_t *elem = type_array_get_element_type(t);
     if (type_array_is_decl_as_ptr(t))
     {
       if (!type_is_alias(elem) && is_array(elem) && !type_array_is_decl_as_ptr(elem))
@@ -461,7 +468,7 @@ void write_type_right(FILE *h, type_t *t, int is_field)
   }
   case TYPE_POINTER:
   {
-    type_t *ref = type_pointer_get_ref(t);
+    type_t *ref = type_pointer_get_ref_type(t);
     if (!type_is_alias(ref) && is_array(ref) && !type_array_is_decl_as_ptr(ref))
       fprintf(h, ")");
     write_type_right(h, ref, FALSE);
@@ -485,30 +492,33 @@ void write_type_right(FILE *h, type_t *t, int is_field)
   }
 }
 
-static void write_type_v(FILE *h, type_t *t, int is_field, int declonly, const char *name)
+static void write_type_v(FILE *h, const decl_spec_t *ds, int is_field, int declonly, const char *name)
 {
+  type_t *t = ds->type;
   type_t *pt = NULL;
   int ptr_level = 0;
 
   if (!h) return;
 
   if (t) {
-    for (pt = t; is_ptr(pt); pt = type_pointer_get_ref(pt), ptr_level++)
+    const decl_spec_t *dpt = NULL;
+    for (dpt = ds; is_ptr(dpt->type); dpt = type_pointer_get_ref(dpt->type), ptr_level++)
       ;
+    pt = dpt->type;
 
     if (type_get_type_detect_alias(pt) == TYPE_FUNCTION) {
       int i;
       const char *callconv = get_attrp(pt->attrs, ATTR_CALLCONV);
       if (!callconv && is_object_interface) callconv = "STDMETHODCALLTYPE";
-      if (is_attr(pt->attrs, ATTR_INLINE)) fprintf(h, "inline ");
-      write_type_left(h, type_function_get_rettype(pt), NAME_DEFAULT, declonly);
+      if (!is_ptr(ds->type) && dpt->funcspecifier == FUNCTION_SPECIFIER_INLINE) fprintf(h, "inline ");
+      write_declspec_left(h, type_function_get_retdeclspec(pt), NAME_DEFAULT, declonly);
       fputc(' ', h);
       if (ptr_level) fputc('(', h);
       if (callconv) fprintf(h, "%s ", callconv);
       for (i = 0; i < ptr_level; i++)
         fputc('*', h);
     } else
-      write_type_left(h, t, NAME_DEFAULT, declonly);
+      write_declspec_left(h, ds, NAME_DEFAULT, declonly);
   }
 
   if (name) fprintf(h, "%s%s", !t || needs_space_after(t) ? " " : "", name );
@@ -529,12 +539,7 @@ static void write_type_v(FILE *h, type_t *t, int is_field, int declonly, const c
   }
 }
 
-static void write_type_def_or_decl(FILE *f, type_t *t, int field, const char *name)
-{
-  write_type_v(f, t, field, FALSE, name);
-}
-
-static void write_type_definition(FILE *f, type_t *t)
+static void write_type_definition(FILE *f, type_t *t, int declonly)
 {
     int in_namespace = t->namespace && !is_global_namespace(t->namespace);
     int save_written = t->written;
@@ -545,14 +550,14 @@ static void write_type_definition(FILE *f, type_t *t)
         write_namespace_start(f, t->namespace);
     }
     indent(f, 0);
-    write_type_left(f, t, NAME_DEFAULT, FALSE);
+    write_type_left(f, t, NAME_DEFAULT, declonly);
     fprintf(f, ";\n");
     if(in_namespace) {
         t->written = save_written;
         write_namespace_end(f, t->namespace);
         fprintf(f, "extern \"C\" {\n");
         fprintf(f, "#else\n");
-        write_type_left(f, t, NAME_C, FALSE);
+        write_type_left(f, t, NAME_C, declonly);
         fprintf(f, ";\n");
         fprintf(f, "#endif\n\n");
     }
@@ -560,12 +565,18 @@ static void write_type_definition(FILE *f, type_t *t)
 
 void write_type_decl(FILE *f, type_t *t, const char *name)
 {
-  write_type_v(f, t, FALSE, TRUE, name);
+  decl_spec_t ds;
+  write_declspec_decl(f, init_declspec(&ds, t), name);
+}
+
+void write_declspec_decl(FILE *f, const decl_spec_t *ds, const char *name)
+{
+  write_type_v(f, ds, FALSE, TRUE, name);
 }
 
-void write_type_decl_left(FILE *f, type_t *t)
+void write_declspec_decl_left(FILE *f, const decl_spec_t *ds)
 {
-  write_type_left(f, t, NAME_DEFAULT, TRUE);
+  write_declspec_left(f, ds, NAME_DEFAULT, TRUE);
 }
 
 static int user_type_registered(const char *name)
@@ -602,8 +613,8 @@ unsigned int get_context_handle_offset( const type_t *type )
 
     while (!is_attr( type->attrs, ATTR_CONTEXTHANDLE ))
     {
-        if (type_is_alias( type )) type = type_alias_get_aliasee( type );
-        else if (is_ptr( type )) type = type_pointer_get_ref( type );
+        if (type_is_alias( type )) type = type_alias_get_aliasee_type( type );
+        else if (is_ptr( type )) type = type_pointer_get_ref_type( type );
         else error( "internal error: %s is not a context handle\n", type->name );
     }
     LIST_FOR_EACH_ENTRY( ch, &context_handle_list, context_handle_t, entry )
@@ -622,8 +633,8 @@ unsigned int get_generic_handle_offset( const type_t *type )
 
     while (!is_attr( type->attrs, ATTR_HANDLE ))
     {
-        if (type_is_alias( type )) type = type_alias_get_aliasee( type );
-        else if (is_ptr( type )) type = type_pointer_get_ref( type );
+        if (type_is_alias( type )) type = type_alias_get_aliasee_type( type );
+        else if (is_ptr( type )) type = type_pointer_get_ref_type( type );
         else error( "internal error: %s is not a generic handle\n", type->name );
     }
     LIST_FOR_EACH_ENTRY( gh, &generic_handle_list, generic_handle_t, entry )
@@ -637,82 +648,77 @@ unsigned int get_generic_handle_offset( const type_t *type )
 
 /* check for types which require additional prototypes to be generated in the
  * header */
-void check_for_additional_prototype_types(const var_list_t *list)
-{
-  const var_t *v;
-
-  if (!list) return;
-  LIST_FOR_EACH_ENTRY( v, list, const var_t, entry )
-  {
-    type_t *type = v->type;
-    if (!type) continue;
-    for (;;) {
-      const char *name = type->name;
-      if (type->user_types_registered) break;
-      type->user_types_registered = 1;
-      if (is_attr(type->attrs, ATTR_CONTEXTHANDLE)) {
-        if (!context_handle_registered(name))
-        {
-          context_handle_t *ch = xmalloc(sizeof(*ch));
-          ch->name = xstrdup(name);
-          list_add_tail(&context_handle_list, &ch->entry);
-        }
-        /* don't carry on parsing fields within this type */
-        break;
-      }
-      if ((type_get_type(type) != TYPE_BASIC ||
-           type_basic_get_type(type) != TYPE_BASIC_HANDLE) &&
-          is_attr(type->attrs, ATTR_HANDLE)) {
-        if (!generic_handle_registered(name))
-        {
-          generic_handle_t *gh = xmalloc(sizeof(*gh));
-          gh->name = xstrdup(name);
-          list_add_tail(&generic_handle_list, &gh->entry);
-        }
-        /* don't carry on parsing fields within this type */
-        break;
+void check_for_additional_prototype_types(type_t *type)
+{
+  if (!type) return;
+  for (;;) {
+    const char *name = type->name;
+    if (type->user_types_registered) break;
+    type->user_types_registered = 1;
+    if (is_attr(type->attrs, ATTR_CONTEXTHANDLE)) {
+      if (!context_handle_registered(name))
+      {
+        context_handle_t *ch = xmalloc(sizeof(*ch));
+        ch->name = xstrdup(name);
+        list_add_tail(&context_handle_list, &ch->entry);
       }
-      if (is_attr(type->attrs, ATTR_WIREMARSHAL)) {
-        if (!user_type_registered(name))
-        {
-          user_type_t *ut = xmalloc(sizeof *ut);
-          ut->name = xstrdup(name);
-          list_add_tail(&user_type_list, &ut->entry);
-        }
-        /* don't carry on parsing fields within this type as we are already
-         * using a wire marshaled type */
-        break;
+      /* don't carry on parsing fields within this type */
+      break;
+    }
+    if ((type_get_type(type) != TYPE_BASIC ||
+         type_basic_get_type(type) != TYPE_BASIC_HANDLE) &&
+        is_attr(type->attrs, ATTR_HANDLE)) {
+      if (!generic_handle_registered(name))
+      {
+        generic_handle_t *gh = xmalloc(sizeof(*gh));
+        gh->name = xstrdup(name);
+        list_add_tail(&generic_handle_list, &gh->entry);
       }
-      else if (type_is_complete(type))
+      /* don't carry on parsing fields within this type */
+      break;
+    }
+    if (is_attr(type->attrs, ATTR_WIREMARSHAL)) {
+      if (!user_type_registered(name))
       {
-        var_list_t *vars;
-        switch (type_get_type_detect_alias(type))
-        {
-        case TYPE_ENUM:
-          vars = type_enum_get_values(type);
-          break;
-        case TYPE_STRUCT:
-          vars = type_struct_get_fields(type);
-          break;
-        case TYPE_UNION:
-          vars = type_union_get_cases(type);
-          break;
-        default:
-          vars = NULL;
-          break;
-        }
-        check_for_additional_prototype_types(vars);
+        user_type_t *ut = xmalloc(sizeof *ut);
+        ut->name = xstrdup(name);
+        list_add_tail(&user_type_list, &ut->entry);
       }
-
-      if (type_is_alias(type))
-        type = type_alias_get_aliasee(type);
-      else if (is_ptr(type))
-        type = type_pointer_get_ref(type);
-      else if (is_array(type))
-        type = type_array_get_element(type);
-      else
+      /* don't carry on parsing fields within this type as we are already
+       * using a wire marshaled type */
+      break;
+    }
+    else if (type_is_complete(type))
+    {
+      var_list_t *vars;
+      const var_t *v;
+      switch (type_get_type_detect_alias(type))
+      {
+      case TYPE_ENUM:
+        vars = type_enum_get_values(type);
+        break;
+      case TYPE_STRUCT:
+        vars = type_struct_get_fields(type);
         break;
+      case TYPE_UNION:
+        vars = type_union_get_cases(type);
+        break;
+      default:
+        vars = NULL;
+        break;
+      }
+      if (vars) LIST_FOR_EACH_ENTRY( v, vars, const var_t, entry )
+        check_for_additional_prototype_types(v->declspec.type);
     }
+
+    if (type_is_alias(type))
+      type = type_alias_get_aliasee_type(type);
+    else if (is_ptr(type))
+      type = type_pointer_get_ref_type(type);
+    else if (is_array(type))
+      type = type_array_get_element_type(type);
+    else
+      break;
   }
 }
 
@@ -791,26 +797,26 @@ static void write_generic_handle_routines(FILE *header)
   }
 }
 
-static void write_typedef(FILE *header, type_t *type)
+static void write_typedef(FILE *header, type_t *type, int declonly)
 {
   fprintf(header, "typedef ");
-  write_type_def_or_decl(header, type_alias_get_aliasee(type), FALSE, type->name);
+  write_type_v(header, type_alias_get_aliasee(type), FALSE, declonly, type->name);
   fprintf(header, ";\n");
 }
 
 int is_const_decl(const var_t *var)
 {
-  const type_t *t;
+  const decl_spec_t *ds;
   /* strangely, MIDL accepts a const attribute on any pointer in the
   * declaration to mean that data isn't being instantiated. this appears
   * to be a bug, but there is no benefit to being incompatible with MIDL,
   * so we'll do the same thing */
-  for (t = var->type; ; )
+  for (ds = &var->declspec; ;)
   {
-    if (is_attr(t->attrs, ATTR_CONST))
+    if (ds->typequalifier == TYPE_QUALIFIER_CONST)
       return TRUE;
-    else if (is_ptr(t))
-      t = type_pointer_get_ref(t);
+    else if (is_ptr(ds->type))
+      ds = type_pointer_get_ref(ds->type);
     else break;
   }
   return FALSE;
@@ -826,7 +832,7 @@ static void write_declaration(FILE *header, const var_t *v)
   }
   else
   {
-    switch (v->stgclass)
+    switch (v->declspec.stgclass)
     {
       case STG_NONE:
       case STG_REGISTER: /* ignored */
@@ -838,7 +844,7 @@ static void write_declaration(FILE *header, const var_t *v)
         fprintf(header, "extern ");
         break;
     }
-    write_type_def_or_decl(header, v->type, FALSE, v->name);
+    write_type_v(header, &v->declspec, FALSE, FALSE, v->name);
     fprintf(header, ";\n\n");
   }
 }
@@ -855,9 +861,9 @@ static void write_library(FILE *header, const typelib_t *typelib)
 const type_t* get_explicit_generic_handle_type(const var_t* var)
 {
     const type_t *t;
-    for (t = var->type;
+    for (t = var->declspec.type;
          is_ptr(t) || type_is_alias(t);
-         t = type_is_alias(t) ? type_alias_get_aliasee(t) : type_pointer_get_ref(t))
+         t = type_is_alias(t) ? type_alias_get_aliasee_type(t) : type_pointer_get_ref_type(t))
         if ((type_get_type_detect_alias(t) != TYPE_BASIC || type_basic_get_type(t) != TYPE_BASIC_HANDLE) &&
             is_attr(t->attrs, ATTR_HANDLE))
             return t;
@@ -868,13 +874,13 @@ const var_t *get_func_handle_var( const type_t *iface, const var_t *func,
                                   unsigned char *explicit_fc, unsigned char *implicit_fc )
 {
     const var_t *var;
-    const var_list_t *args = type_get_function_args( func->type );
+    const var_list_t *args = type_function_get_args( func->declspec.type );
 
     *explicit_fc = *implicit_fc = 0;
     if (args) LIST_FOR_EACH_ENTRY( var, args, const var_t, entry )
     {
         if (!is_attr( var->attrs, ATTR_IN ) && is_attr( var->attrs, ATTR_OUT )) continue;
-        if (type_get_type( var->type ) == TYPE_BASIC && type_basic_get_type( var->type ) == TYPE_BASIC_HANDLE)
+        if (type_get_type( var->declspec.type ) == TYPE_BASIC && type_basic_get_type( var->declspec.type ) == TYPE_BASIC_HANDLE)
         {
             *explicit_fc = FC_BIND_PRIMITIVE;
             return var;
@@ -884,7 +890,7 @@ const var_t *get_func_handle_var( const type_t *iface, const var_t *func,
             *explicit_fc = FC_BIND_GENERIC;
             return var;
         }
-        if (is_context_handle( var->type ))
+        if (is_context_handle( var->declspec.type ))
         {
             *explicit_fc = FC_BIND_CONTEXT;
             return var;
@@ -893,8 +899,8 @@ const var_t *get_func_handle_var( const type_t *iface, const var_t *func,
 
     if ((var = get_attrp( iface->attrs, ATTR_IMPLICIT_HANDLE )))
     {
-        if (type_get_type( var->type ) == TYPE_BASIC &&
-            type_basic_get_type( var->type ) == TYPE_BASIC_HANDLE)
+        if (type_get_type( var->declspec.type ) == TYPE_BASIC &&
+            type_basic_get_type( var->declspec.type ) == TYPE_BASIC_HANDLE)
             *implicit_fc = FC_BIND_PRIMITIVE;
         else
             *implicit_fc = FC_BIND_GENERIC;
@@ -909,13 +915,13 @@ int has_out_arg_or_return(const var_t *func)
 {
     const var_t *var;
 
-    if (!is_void(type_function_get_rettype(func->type)))
+    if (!is_void(type_function_get_rettype(func->declspec.type)))
         return 1;
 
-    if (!type_get_function_args(func->type))
+    if (!type_function_get_args(func->declspec.type))
         return 0;
 
-    LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
+    LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), const var_t, entry )
         if (is_attr(var->attrs, ATTR_OUT))
             return 1;
 
@@ -995,7 +1001,7 @@ static int is_override_method(const type_t *iface, const type_t *child, const va
 
 static int is_aggregate_return(const var_t *func)
 {
-  enum type_type type = type_get_type(type_function_get_rettype(func->type));
+  enum type_type type = type_get_type(type_function_get_rettype(func->declspec.type));
   return type == TYPE_STRUCT || type == TYPE_UNION ||
          type == TYPE_COCLASS || type == TYPE_INTERFACE;
 }
@@ -1035,8 +1041,8 @@ static void write_method_macro(FILE *header, const type_t *iface, const type_t *
       const var_t *arg;
 
       fprintf(header, "#define %s_%s(This", name, get_name(func));
-      if (type_get_function_args(func->type))
-          LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), const var_t, entry )
+      if (type_function_get_args(func->declspec.type))
+          LIST_FOR_EACH_ENTRY( arg, type_function_get_args(func->declspec.type), const var_t, entry )
               fprintf(header, ",%s", arg->name);
       fprintf(header, ") ");
 
@@ -1047,8 +1053,8 @@ static void write_method_macro(FILE *header, const type_t *iface, const type_t *
       }
 
       fprintf(header, "(This)->lpVtbl->%s(This", get_vtbl_entry_name(iface, func));
-      if (type_get_function_args(func->type))
-          LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), const var_t, entry )
+      if (type_function_get_args(func->declspec.type))
+          LIST_FOR_EACH_ENTRY( arg, type_function_get_args(func->declspec.type), const var_t, entry )
               fprintf(header, ",%s", arg->name);
       fprintf(header, ")\n");
     }
@@ -1078,7 +1084,7 @@ void write_args(FILE *h, const var_list_t *args, const char *name, int method, i
         }
         else fprintf(h, ",");
     }
-    write_type_decl(h, arg->type, arg->name);
+    write_declspec_decl(h, &arg->declspec, arg->name);
     if (method == 2) {
         const expr_t *expr = get_attrp(arg->attrs, ATTR_DEFAULTVALUE);
         if (expr) {
@@ -1090,7 +1096,7 @@ void write_args(FILE *h, const var_list_t *args, const char *name, int method, i
                     expr_t bstr;
 
                     /* Fixup the expression type for a BSTR like midl does. */
-                    if (get_type_vt(arg->type) == VT_BSTR && expr->type == EXPR_STRLIT)
+                    if (get_type_vt(arg->declspec.type) == VT_BSTR && expr->type == EXPR_STRLIT)
                     {
                         bstr = *expr;
                         bstr.type = EXPR_WSTRLIT;
@@ -1119,8 +1125,8 @@ static void write_cpp_method_def(FILE *header, const type_t *iface)
   {
     const var_t *func = stmt->u.var;
     if (!is_callas(func->attrs)) {
-      const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV);
-      const var_list_t *args = type_get_function_args(func->type);
+      const char *callconv = get_attrp(func->declspec.type->attrs, ATTR_CALLCONV);
+      const var_list_t *args = type_function_get_args(func->declspec.type);
       const var_t *arg;
 
       if (!callconv) callconv = "STDMETHODCALLTYPE";
@@ -1130,11 +1136,11 @@ static void write_cpp_method_def(FILE *header, const type_t *iface)
 
         indent(header, 0);
         fprintf(header, "virtual ");
-        write_type_decl_left(header, type_function_get_rettype(func->type));
+        write_declspec_decl_left(header, type_function_get_retdeclspec(func->declspec.type));
         fprintf(header, "* %s %s(\n", callconv, get_name(func));
         ++indentation;
         indent(header, 0);
-        write_type_decl_left(header, type_function_get_rettype(func->type));
+        write_declspec_decl_left(header, type_function_get_retdeclspec(func->declspec.type));
         fprintf(header, " *__ret");
         --indentation;
         if (args) {
@@ -1144,7 +1150,7 @@ static void write_cpp_method_def(FILE *header, const type_t *iface)
         fprintf(header, ") = 0;\n");
 
         indent(header, 0);
-        write_type_decl_left(header, type_function_get_rettype(func->type));
+        write_declspec_decl_left(header, type_function_get_retdeclspec(func->declspec.type));
         fprintf(header, " %s %s(\n", callconv, get_name(func));
         write_args(header, args, iface->name, 2, TRUE);
         fprintf(header, ")\n");
@@ -1152,7 +1158,7 @@ static void write_cpp_method_def(FILE *header, const type_t *iface)
         fprintf(header, "{\n");
         ++indentation;
         indent(header, 0);
-        write_type_decl_left(header, type_function_get_rettype(func->type));
+        write_declspec_decl_left(header, type_function_get_retdeclspec(func->declspec.type));
         fprintf(header, " __ret;\n");
         indent(header, 0);
         fprintf(header, "return *%s(&__ret", get_name(func));
@@ -1169,7 +1175,7 @@ static void write_cpp_method_def(FILE *header, const type_t *iface)
 
       indent(header, 0);
       fprintf(header, "virtual ");
-      write_type_decl_left(header, type_function_get_rettype(func->type));
+      write_declspec_decl_left(header, type_function_get_retdeclspec(func->declspec.type));
       fprintf(header, " %s %s(\n", callconv, get_name(func));
       write_args(header, args, iface->name, 2, TRUE);
       fprintf(header, ") = 0;\n");
@@ -1206,25 +1212,25 @@ static void write_inline_wrappers(FILE *header, const type_t *iface, const type_
       const var_t *arg;
 
       fprintf(header, "static FORCEINLINE ");
-      write_type_decl_left(header, type_function_get_rettype(func->type));
+      write_declspec_decl_left(header, type_function_get_retdeclspec(func->declspec.type));
       fprintf(header, " %s_%s(", name, get_name(func));
-      write_args(header, type_get_function_args(func->type), name, 1, FALSE);
+      write_args(header, type_function_get_args(func->declspec.type), name, 1, FALSE);
       fprintf(header, ") {\n");
       ++indentation;
       if (!is_aggregate_return(func)) {
         indent(header, 0);
         fprintf(header, "%sThis->lpVtbl->%s(This",
-                is_void(type_function_get_rettype(func->type)) ? "" : "return ",
+                is_void(type_function_get_rettype(func->declspec.type)) ? "" : "return ",
                 get_vtbl_entry_name(iface, func));
       } else {
         indent(header, 0);
-        write_type_decl_left(header, type_function_get_rettype(func->type));
+        write_declspec_decl_left(header, type_function_get_retdeclspec(func->declspec.type));
         fprintf(header, " __ret;\n");
         indent(header, 0);
         fprintf(header, "return *This->lpVtbl->%s(This,&__ret", get_vtbl_entry_name(iface, func));
       }
-      if (type_get_function_args(func->type))
-          LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), const var_t, entry )
+      if (type_function_get_args(func->declspec.type))
+          LIST_FOR_EACH_ENTRY( arg, type_function_get_args(func->declspec.type), const var_t, entry )
               fprintf(header, ",%s", arg->name);
       fprintf(header, ");\n");
       --indentation;
@@ -1250,10 +1256,10 @@ static void do_write_c_method_def(FILE *header, const type_t *iface, const char
       first_iface = 0;
     }
     if (!is_callas(func->attrs)) {
-      const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV);
+      const char *callconv = get_attrp(func->declspec.type->attrs, ATTR_CALLCONV);
       if (!callconv) callconv = "STDMETHODCALLTYPE";
       indent(header, 0);
-      write_type_decl_left(header, type_function_get_rettype(func->type));
+      write_declspec_decl_left(header, type_function_get_retdeclspec(func->declspec.type));
       if (is_aggregate_return(func))
         fprintf(header, " *");
       if (is_inherited_method(iface, func))
@@ -1266,13 +1272,13 @@ static void do_write_c_method_def(FILE *header, const type_t *iface, const char
       if (is_aggregate_return(func)) {
         fprintf(header, ",\n");
         indent(header, 0);
-        write_type_decl_left(header, type_function_get_rettype(func->type));
+        write_declspec_decl_left(header, type_function_get_retdeclspec(func->declspec.type));
         fprintf(header, " *__ret");
       }
       --indentation;
-      if (type_get_function_args(func->type)) {
+      if (type_function_get_args(func->declspec.type)) {
         fprintf(header, ",\n");
-        write_args(header, type_get_function_args(func->type), name, 0, TRUE);
+        write_args(header, type_function_get_args(func->declspec.type), name, 0, TRUE);
       }
       fprintf(header, ");\n");
       fprintf(header, "\n");
@@ -1299,12 +1305,12 @@ static void write_method_proto(FILE *header, const type_t *iface)
     const var_t *func = stmt->u.var;
 
     if (is_callas(func->attrs)) {
-      const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV);
+      const char *callconv = get_attrp(func->declspec.type->attrs, ATTR_CALLCONV);
       if (!callconv) callconv = "STDMETHODCALLTYPE";
       /* proxy prototype */
-      write_type_decl_left(header, type_function_get_rettype(func->type));
+      write_declspec_decl_left(header, type_function_get_retdeclspec(func->declspec.type));
       fprintf(header, " %s %s_%s_Proxy(\n", callconv, iface->name, get_name(func));
-      write_args(header, type_get_function_args(func->type), iface->name, 1, TRUE);
+      write_args(header, type_function_get_args(func->declspec.type), iface->name, 1, TRUE);
       fprintf(header, ");\n");
       /* stub prototype */
       fprintf(header, "void __RPC_STUB %s_%s_Stub(\n", iface->name, get_name(func));
@@ -1337,12 +1343,12 @@ static void write_locals(FILE *fp, const type_t *iface, int body)
       if (&stmt2->entry != type_iface_get_stmts(iface)) {
         const var_t *m = stmt2->u.var;
         /* proxy prototype - use local prototype */
-        write_type_decl_left(fp, type_function_get_rettype(m->type));
+        write_declspec_decl_left(fp, type_function_get_retdeclspec(m->declspec.type));
         fprintf(fp, " CALLBACK %s_%s_Proxy(\n", iface->name, get_name(m));
-        write_args(fp, type_get_function_args(m->type), iface->name, 1, TRUE);
+        write_args(fp, type_function_get_args(m->declspec.type), iface->name, 1, TRUE);
         fprintf(fp, ")");
         if (body) {
-          type_t *rt = type_function_get_rettype(m->type);
+          type_t *rt = type_function_get_rettype(m->declspec.type);
           fprintf(fp, "\n{\n");
           fprintf(fp, "    %s\n", comment);
           if (rt->name && strcmp(rt->name, "HRESULT") == 0)
@@ -1359,9 +1365,9 @@ static void write_locals(FILE *fp, const type_t *iface, int body)
         else
           fprintf(fp, ";\n");
         /* stub prototype - use remotable prototype */
-        write_type_decl_left(fp, type_function_get_rettype(func->type));
+        write_declspec_decl_left(fp, type_function_get_retdeclspec(func->declspec.type));
         fprintf(fp, " __RPC_STUB %s_%s_Stub(\n", iface->name, get_name(m));
-        write_args(fp, type_get_function_args(func->type), iface->name, 1, TRUE);
+        write_args(fp, type_function_get_args(func->declspec.type), iface->name, 1, TRUE);
         fprintf(fp, ")");
         if (body)
           /* Remotable methods must all return HRESULTs.  */
@@ -1407,15 +1413,16 @@ void write_local_stubs(const statement_list_t *stmts)
 
 static void write_function_proto(FILE *header, const type_t *iface, const var_t *fun, const char *prefix)
 {
-  const char *callconv = get_attrp(fun->type->attrs, ATTR_CALLCONV);
+  const char *callconv = get_attrp(fun->declspec.type->attrs, ATTR_CALLCONV);
 
   if (!callconv) callconv = "__cdecl";
   /* FIXME: do we need to handle call_as? */
-  write_type_decl_left(header, type_function_get_rettype(fun->type));
+  write_declspec_decl_left(header, type_function_get_retdeclspec(fun->declspec.type));
+  if (fun->declspec.funcspecifier == FUNCTION_SPECIFIER_INLINE) fprintf(header, " inline");
   fprintf(header, " %s ", callconv);
   fprintf(header, "%s%s(\n", prefix, get_name(fun));
-  if (type_get_function_args(fun->type))
-    write_args(header, type_get_function_args(fun->type), iface->name, 0, TRUE);
+  if (type_function_get_args(fun->declspec.type))
+    write_args(header, type_function_get_args(fun->declspec.type), iface->name, 0, TRUE);
   else
     fprintf(header, "    void");
   fprintf(header, ");\n\n");
@@ -1541,7 +1548,7 @@ static void write_rpc_interface_start(FILE *header, const type_t *iface)
   if (var)
   {
       fprintf(header, "extern ");
-      write_type_decl( header, var->type, var->name );
+      write_declspec_decl( header, &var->declspec, var->name );
       fprintf(header, ";\n");
   }
   if (old_names)
@@ -1653,6 +1660,7 @@ static void write_forward_decls(FILE *header, const statement_list_t *stmts)
         if (type_get_type(stmt->u.type) == TYPE_INTERFACE)
         {
           type_t *iface = stmt->u.type;
+          assert(type_get_type_detect_alias(iface) == TYPE_INTERFACE);
           if (is_object(iface) || is_attr(iface->attrs, ATTR_DISPINTERFACE))
           {
             write_forward(header, iface);
@@ -1694,6 +1702,7 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons
         {
           type_t *iface = stmt->u.type;
           type_t *async_iface = iface->details.iface->async_iface;
+          assert(type_get_type_detect_alias(iface) == TYPE_INTERFACE);
           if (is_object(iface)) is_object_interface++;
           if (is_attr(stmt->u.type->attrs, ATTR_DISPINTERFACE) || is_object(stmt->u.type))
           {
@@ -1718,7 +1727,7 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons
           write_coclass(header, stmt->u.type);
         else
         {
-          write_type_definition(header, stmt->u.type);
+          write_type_definition(header, stmt->u.type, stmt->declonly);
         }
         break;
       case STMT_TYPEREF:
@@ -1739,7 +1748,7 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons
       {
         const type_list_t *type_entry = stmt->u.type_list;
         for (; type_entry; type_entry = type_entry->next)
-	  write_typedef(header, type_entry->type);
+          write_typedef(header, type_entry->type, stmt->declonly);
         break;
       }
       case STMT_LIBRARY:
@@ -1750,7 +1759,7 @@ static void write_header_stmts(FILE *header, const statement_list_t *stmts, cons
         fprintf(header, "%s\n", stmt->u.str);
         break;
       case STMT_DECLARATION:
-        if (iface && type_get_type(stmt->u.var->type) == TYPE_FUNCTION)
+        if (iface && type_get_type(stmt->u.var->declspec.type) == TYPE_FUNCTION)
         {
           if (!ignore_funcs)
           {
@@ -1784,15 +1793,15 @@ void write_header(const statement_list_t *stmts)
   }
   fprintf(header, "/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n\n", PACKAGE_VERSION, input_name);
 
+  fprintf(header, "#ifdef _WIN32\n");
   fprintf(header, "#ifndef __REQUIRED_RPCNDR_H_VERSION__\n");
   fprintf(header, "#define __REQUIRED_RPCNDR_H_VERSION__ 475\n");
-  fprintf(header, "#endif\n\n");
-
+  fprintf(header, "#endif\n");
   fprintf(header, "#include <rpc.h>\n" );
   fprintf(header, "#include <rpcndr.h>\n" );
   if (!for_each_serializable(stmts, NULL, serializable_exists))
     fprintf(header, "#include <midles.h>\n" );
-  fprintf(header, "\n" );
+  fprintf(header, "#endif\n\n");
 
   fprintf(header, "#ifndef COM_NO_WINDOWS_H\n");
   fprintf(header, "#include <windows.h>\n");
diff --git a/mingw-w64-tools/widl/src/header.h b/mingw-w64-tools/widl/src/header.h
index 0d44b403..0e62f77c 100644
--- a/mingw-w64-tools/widl/src/header.h
+++ b/mingw-w64-tools/widl/src/header.h
@@ -29,10 +29,12 @@ extern int is_attr(const attr_list_t *list, enum attr_type t);
 extern void *get_attrp(const attr_list_t *list, enum attr_type t);
 extern unsigned int get_attrv(const attr_list_t *list, enum attr_type t);
 extern const char* get_name(const var_t *v);
+extern void write_declspec_left(FILE *h, const decl_spec_t *ds, enum name_type name_type, int declonly);
 extern void write_type_left(FILE *h, type_t *t, enum name_type name_type, int declonly);
 extern void write_type_right(FILE *h, type_t *t, int is_field);
 extern void write_type_decl(FILE *f, type_t *t, const char *name);
-extern void write_type_decl_left(FILE *f, type_t *t);
+extern void write_declspec_decl(FILE *f, const decl_spec_t *ds, const char *name);
+extern void write_declspec_decl_left(FILE *f, const decl_spec_t *ds);
 extern unsigned int get_context_handle_offset( const type_t *type );
 extern unsigned int get_generic_handle_offset( const type_t *type );
 extern int needs_space_after(type_t *t);
@@ -83,12 +85,12 @@ static inline int is_conformant_array(const type_t *t)
 
 static inline int last_ptr(const type_t *type)
 {
-    return is_ptr(type) && !is_declptr(type_pointer_get_ref(type));
+    return is_ptr(type) && !is_declptr(type_pointer_get_ref_type(type));
 }
 
 static inline int last_array(const type_t *type)
 {
-    return is_array(type) && !is_array(type_array_get_element(type));
+    return is_array(type) && !is_array(type_array_get_element_type(type));
 }
 
 static inline int is_string_type(const attr_list_t *attrs, const type_t *type)
@@ -102,7 +104,7 @@ static inline int is_context_handle(const type_t *type)
     const type_t *t;
     for (t = type;
          is_ptr(t) || type_is_alias(t);
-         t = type_is_alias(t) ? type_alias_get_aliasee(t) : type_pointer_get_ref(t))
+         t = type_is_alias(t) ? type_alias_get_aliasee_type(t) : type_pointer_get_ref_type(t))
         if (is_attr(t->attrs, ATTR_CONTEXTHANDLE))
             return 1;
     return 0;
diff --git a/mingw-w64-tools/widl/src/parser.tab.c b/mingw-w64-tools/widl/src/parser.tab.c
index 6266e054..8cd1605a 100644
--- a/mingw-w64-tools/widl/src/parser.tab.c
+++ b/mingw-w64-tools/widl/src/parser.tab.c
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.0.5.  */
+/* A Bison parser, made by GNU Bison 3.0.4.  */
 
 /* Bison implementation for Yacc-like parsers in C
 
-   Copyright (C) 1984, 1989-1990, 2000-2015, 2018 Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -44,7 +44,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "3.0.5"
+#define YYBISON_VERSION "3.0.4"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -125,13 +125,6 @@ struct _import_t
   int import_performed;
 };
 
-typedef struct _decl_spec_t
-{
-  type_t *type;
-  attr_list_t *attrs;
-  enum storage_class stgclass;
-} decl_spec_t;
-
 typelist_t incomplete_types = LIST_INIT(incomplete_types);
 
 static void fix_incomplete(void);
@@ -140,7 +133,7 @@ static void fix_incomplete_types(type_t *complete_type);
 static str_list_t *append_str(str_list_t *list, char *str);
 static attr_list_t *append_attr(attr_list_t *list, attr_t *attr);
 static attr_list_t *append_attr_list(attr_list_t *new_list, attr_list_t *old_list);
-static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, attr_t *attr, enum storage_class stgclass);
+static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, enum storage_class stgclass, enum type_qualifier typequalifier, enum function_specifier funcspecifier);
 static attr_t *make_attr(enum attr_type type);
 static attr_t *make_attrv(enum attr_type type, unsigned int val);
 static attr_t *make_attrp(enum attr_type type, void *val);
@@ -156,6 +149,7 @@ static declarator_t *make_declarator(var_t *var);
 static type_t *make_safearray(type_t *type);
 static typelib_t *make_library(const char *name, const attr_list_t *attrs);
 static type_t *append_chain_type(type_t *chain, type_t *type);
+static decl_spec_t *append_chain_declspec(decl_spec_t *chain, type_t *type, enum type_qualifier typequalifier);
 static warning_list_t *append_warning(warning_list_t *, int);
 
 static type_t *reg_typedefs(decl_spec_t *decl_spec, var_list_t *names, attr_list_t *attrs);
@@ -212,7 +206,7 @@ static struct namespace *current_namespace = &global_namespace;
 static typelib_t *current_typelib;
 
 
-#line 216 "parser.tab.c" /* yacc.c:339  */
+#line 210 "parser.tab.c" /* yacc.c:339  */
 
 # ifndef YY_NULLPTR
 #  if defined __cplusplus && 201103L <= __cplusplus
@@ -438,7 +432,7 @@ extern int parser_debug;
 
 union YYSTYPE
 {
-#line 142 "parser.y" /* yacc.c:355  */
+#line 136 "parser.y" /* yacc.c:355  */
 
 	attr_t *attr;
 	attr_list_t *attr_list;
@@ -465,8 +459,10 @@ union YYSTYPE
 	struct _import_t *import;
 	struct _decl_spec_t *declspec;
 	enum storage_class stgclass;
+	enum type_qualifier typequalifier;
+	enum function_specifier funcspecifier;
 
-#line 470 "parser.tab.c" /* yacc.c:355  */
+#line 466 "parser.tab.c" /* yacc.c:355  */
 };
 
 typedef union YYSTYPE YYSTYPE;
@@ -483,7 +479,7 @@ int parser_parse (void);
 
 /* Copy the second part of user declarations.  */
 
-#line 487 "parser.tab.c" /* yacc.c:358  */
+#line 483 "parser.tab.c" /* yacc.c:358  */
 
 #ifdef short
 # undef short
@@ -799,48 +795,48 @@ static const yytype_uint8 yytranslate[] =
   /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   325,   325,   340,   340,   342,   343,   343,   345,   346,
-     347,   350,   353,   354,   355,   358,   359,   360,   360,   362,
-     363,   364,   367,   368,   369,   370,   373,   374,   377,   378,
-     382,   383,   384,   385,   386,   387,   388,   391,   402,   403,
-     407,   408,   409,   410,   411,   412,   413,   414,   415,   418,
-     420,   428,   434,   438,   439,   441,   445,   449,   450,   453,
-     454,   457,   458,   462,   467,   474,   478,   479,   482,   483,
-     487,   490,   491,   492,   495,   496,   499,   500,   501,   502,
-     503,   504,   505,   506,   507,   508,   509,   510,   511,   512,
-     513,   514,   515,   516,   517,   518,   519,   520,   521,   522,
-     523,   524,   525,   526,   527,   528,   529,   530,   531,   532,
-     533,   534,   535,   536,   537,   538,   539,   540,   541,   542,
-     543,   544,   545,   546,   547,   548,   549,   550,   551,   552,
-     553,   554,   555,   556,   557,   558,   559,   560,   561,   562,
-     563,   564,   565,   566,   567,   568,   569,   570,   571,   572,
-     573,   574,   578,   579,   580,   581,   582,   583,   584,   585,
-     586,   587,   588,   589,   590,   591,   592,   593,   594,   595,
-     596,   597,   598,   599,   600,   601,   605,   606,   611,   612,
-     613,   614,   617,   618,   621,   625,   631,   632,   633,   636,
-     640,   652,   656,   661,   664,   665,   668,   669,   672,   673,
-     674,   675,   676,   677,   678,   679,   680,   681,   682,   683,
-     684,   685,   686,   687,   688,   689,   690,   691,   692,   693,
-     694,   695,   696,   697,   698,   699,   700,   701,   702,   703,
-     704,   705,   706,   707,   708,   709,   711,   713,   714,   717,
-     718,   721,   727,   733,   734,   737,   742,   749,   750,   753,
-     754,   758,   759,   762,   766,   772,   780,   784,   789,   790,
-     793,   794,   795,   798,   800,   803,   804,   805,   806,   807,
-     808,   809,   810,   811,   812,   813,   816,   817,   820,   821,
-     822,   823,   824,   825,   826,   827,   828,   831,   832,   840,
-     846,   850,   853,   854,   858,   861,   862,   865,   874,   875,
-     878,   879,   882,   888,   894,   895,   898,   899,   902,   912,
-     922,   928,   932,   933,   936,   937,   940,   945,   952,   953,
-     954,   958,   962,   965,   966,   969,   970,   974,   975,   979,
-     980,   981,   985,   987,   989,   993,   994,   995,   996,  1004,
-    1006,  1008,  1013,  1015,  1020,  1021,  1026,  1027,  1028,  1029,
-    1034,  1043,  1045,  1046,  1051,  1053,  1057,  1058,  1065,  1066,
-    1067,  1068,  1069,  1074,  1082,  1083,  1086,  1087,  1090,  1097,
-    1098,  1103,  1104,  1108,  1109,  1110,  1111,  1112,  1116,  1117,
-    1118,  1121,  1124,  1125,  1126,  1127,  1128,  1129,  1130,  1131,
-    1132,  1133,  1136,  1143,  1145,  1151,  1152,  1153,  1156,  1158,
-    1160,  1162,  1165,  1170,  1178,  1179,  1182,  1183,  1186,  1187,
-    1188
+       0,   323,   323,   338,   338,   340,   341,   341,   343,   344,
+     345,   348,   351,   352,   353,   356,   357,   358,   358,   360,
+     361,   362,   365,   366,   367,   368,   371,   372,   375,   376,
+     380,   381,   382,   383,   384,   385,   386,   389,   400,   401,
+     405,   406,   407,   408,   409,   410,   411,   412,   413,   416,
+     418,   426,   432,   436,   437,   439,   443,   447,   448,   451,
+     452,   455,   456,   460,   465,   472,   476,   477,   480,   481,
+     485,   488,   489,   490,   493,   494,   497,   498,   499,   500,
+     501,   502,   503,   504,   505,   506,   507,   508,   509,   510,
+     511,   512,   513,   514,   515,   516,   517,   518,   519,   520,
+     521,   522,   523,   524,   525,   526,   527,   528,   529,   530,
+     531,   532,   533,   534,   535,   536,   537,   538,   539,   540,
+     541,   542,   543,   544,   545,   546,   547,   548,   549,   550,
+     551,   552,   553,   554,   555,   556,   557,   558,   559,   560,
+     561,   562,   563,   564,   565,   566,   567,   568,   569,   570,
+     571,   572,   576,   577,   578,   579,   580,   581,   582,   583,
+     584,   585,   586,   587,   588,   589,   590,   591,   592,   593,
+     594,   595,   596,   597,   598,   599,   603,   604,   609,   610,
+     611,   612,   615,   616,   619,   623,   629,   630,   631,   634,
+     638,   650,   654,   659,   662,   663,   666,   667,   670,   671,
+     672,   673,   674,   675,   676,   677,   678,   679,   680,   681,
+     682,   683,   684,   685,   686,   687,   688,   689,   690,   691,
+     692,   693,   694,   695,   696,   697,   698,   699,   700,   701,
+     702,   703,   704,   705,   706,   707,   709,   711,   712,   715,
+     716,   719,   725,   731,   732,   735,   740,   747,   748,   751,
+     752,   756,   757,   760,   764,   770,   778,   782,   787,   788,
+     791,   792,   793,   796,   798,   801,   802,   803,   804,   805,
+     806,   807,   808,   809,   810,   811,   814,   815,   818,   819,
+     820,   821,   822,   823,   824,   825,   826,   829,   830,   838,
+     844,   848,   851,   852,   856,   859,   860,   863,   872,   873,
+     876,   877,   880,   886,   892,   893,   896,   897,   900,   910,
+     920,   926,   930,   931,   934,   935,   938,   943,   950,   951,
+     952,   956,   960,   963,   964,   967,   968,   972,   973,   977,
+     978,   979,   983,   985,   987,   991,   992,   993,   994,  1002,
+    1004,  1006,  1011,  1013,  1018,  1019,  1024,  1025,  1026,  1027,
+    1032,  1041,  1043,  1044,  1049,  1051,  1055,  1056,  1063,  1064,
+    1065,  1066,  1067,  1072,  1080,  1081,  1084,  1085,  1088,  1095,
+    1096,  1101,  1102,  1106,  1107,  1108,  1109,  1110,  1114,  1115,
+    1116,  1119,  1122,  1123,  1124,  1125,  1126,  1127,  1128,  1129,
+    1130,  1131,  1134,  1141,  1143,  1149,  1150,  1151,  1154,  1156,
+    1158,  1160,  1163,  1168,  1176,  1177,  1180,  1181,  1184,  1185,
+    1186
 };
 #endif
 
@@ -903,7 +899,7 @@ static const char *const yytname[] =
   "dispinterfacedef", "inherit", "interface", "interfacehdr",
   "interfacedef", "interfacedec", "module", "modulehdr", "moduledef",
   "storage_cls_spec", "function_specifier", "type_qualifier",
-  "m_type_qual_list", "decl_spec", "m_decl_spec_no_type",
+  "m_type_qual_bits", "decl_spec", "m_decl_spec_no_type",
   "decl_spec_no_type", "declarator", "direct_declarator",
   "abstract_declarator", "abstract_declarator_no_direct",
   "m_abstract_declarator", "abstract_direct_declarator", "any_declarator",
@@ -2298,7 +2294,6 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
       case N:                               \
         yyformat = S;                       \
       break
-    default: /* Avoid compiler warnings. */
       YYCASE_(0, YY_("syntax error"));
       YYCASE_(1, YY_("syntax error, unexpected %s"));
       YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
@@ -2615,7 +2610,7 @@ yyreduce:
   switch (yyn)
     {
         case 2:
-#line 325 "parser.y" /* yacc.c:1648  */
+#line 323 "parser.y" /* yacc.c:1646  */
     { fix_incomplete();
 						  check_statements((yyvsp[-1].stmt_list), FALSE);
 						  check_all_user_types((yyvsp[-1].stmt_list));
@@ -2629,197 +2624,197 @@ yyreduce:
 						  write_dlldata((yyvsp[-1].stmt_list));
 						  write_local_stubs((yyvsp[-1].stmt_list));
 						}
-#line 2633 "parser.tab.c" /* yacc.c:1648  */
+#line 2628 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 5:
-#line 342 "parser.y" /* yacc.c:1648  */
+#line 340 "parser.y" /* yacc.c:1646  */
     { (yyval.stmt_list) = NULL; }
-#line 2639 "parser.tab.c" /* yacc.c:1648  */
+#line 2634 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 6:
-#line 343 "parser.y" /* yacc.c:1648  */
+#line 341 "parser.y" /* yacc.c:1646  */
     { push_namespace((yyvsp[-1].str)); }
-#line 2645 "parser.tab.c" /* yacc.c:1648  */
+#line 2640 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 7:
-#line 344 "parser.y" /* yacc.c:1648  */
+#line 342 "parser.y" /* yacc.c:1646  */
     { pop_namespace((yyvsp[-4].str)); (yyval.stmt_list) = append_statements((yyvsp[-5].stmt_list), (yyvsp[-1].stmt_list)); }
-#line 2651 "parser.tab.c" /* yacc.c:1648  */
+#line 2646 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 8:
-#line 345 "parser.y" /* yacc.c:1648  */
+#line 343 "parser.y" /* yacc.c:1646  */
     { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_reference((yyvsp[0].type))); }
-#line 2657 "parser.tab.c" /* yacc.c:1648  */
+#line 2652 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 9:
-#line 346 "parser.y" /* yacc.c:1648  */
+#line 344 "parser.y" /* yacc.c:1646  */
     { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_type_decl((yyvsp[0].type))); }
-#line 2663 "parser.tab.c" /* yacc.c:1648  */
+#line 2658 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 10:
-#line 347 "parser.y" /* yacc.c:1648  */
+#line 345 "parser.y" /* yacc.c:1646  */
     { (yyval.stmt_list) = (yyvsp[-2].stmt_list);
 						  reg_type((yyvsp[-1].type), (yyvsp[-1].type)->name, current_namespace, 0);
 						}
-#line 2671 "parser.tab.c" /* yacc.c:1648  */
+#line 2666 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 11:
-#line 350 "parser.y" /* yacc.c:1648  */
+#line 348 "parser.y" /* yacc.c:1646  */
     { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_type_decl((yyvsp[0].type)));
 						  reg_type((yyvsp[0].type), (yyvsp[0].type)->name, current_namespace, 0);
 						}
-#line 2679 "parser.tab.c" /* yacc.c:1648  */
+#line 2674 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 12:
-#line 353 "parser.y" /* yacc.c:1648  */
+#line 351 "parser.y" /* yacc.c:1646  */
     { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_module((yyvsp[0].type))); }
-#line 2685 "parser.tab.c" /* yacc.c:1648  */
+#line 2680 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 13:
-#line 354 "parser.y" /* yacc.c:1648  */
+#line 352 "parser.y" /* yacc.c:1646  */
     { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_library((yyvsp[0].typelib))); }
-#line 2691 "parser.tab.c" /* yacc.c:1648  */
+#line 2686 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 14:
-#line 355 "parser.y" /* yacc.c:1648  */
+#line 353 "parser.y" /* yacc.c:1646  */
     { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), (yyvsp[0].statement)); }
-#line 2697 "parser.tab.c" /* yacc.c:1648  */
+#line 2692 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 15:
-#line 358 "parser.y" /* yacc.c:1648  */
+#line 356 "parser.y" /* yacc.c:1646  */
     { (yyval.stmt_list) = NULL; }
-#line 2703 "parser.tab.c" /* yacc.c:1648  */
+#line 2698 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 16:
-#line 359 "parser.y" /* yacc.c:1648  */
+#line 357 "parser.y" /* yacc.c:1646  */
     { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_reference((yyvsp[0].type))); }
-#line 2709 "parser.tab.c" /* yacc.c:1648  */
+#line 2704 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 17:
-#line 360 "parser.y" /* yacc.c:1648  */
+#line 358 "parser.y" /* yacc.c:1646  */
     { push_namespace((yyvsp[-1].str)); }
-#line 2715 "parser.tab.c" /* yacc.c:1648  */
+#line 2710 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 18:
-#line 361 "parser.y" /* yacc.c:1648  */
+#line 359 "parser.y" /* yacc.c:1646  */
     { pop_namespace((yyvsp[-4].str)); (yyval.stmt_list) = append_statements((yyvsp[-5].stmt_list), (yyvsp[-1].stmt_list)); }
-#line 2721 "parser.tab.c" /* yacc.c:1648  */
+#line 2716 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 19:
-#line 362 "parser.y" /* yacc.c:1648  */
+#line 360 "parser.y" /* yacc.c:1646  */
     { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_type_decl((yyvsp[0].type))); }
-#line 2727 "parser.tab.c" /* yacc.c:1648  */
+#line 2722 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 20:
-#line 363 "parser.y" /* yacc.c:1648  */
+#line 361 "parser.y" /* yacc.c:1646  */
     { (yyval.stmt_list) = (yyvsp[-2].stmt_list); reg_type((yyvsp[-1].type), (yyvsp[-1].type)->name, current_namespace, 0); }
-#line 2733 "parser.tab.c" /* yacc.c:1648  */
+#line 2728 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 21:
-#line 364 "parser.y" /* yacc.c:1648  */
+#line 362 "parser.y" /* yacc.c:1646  */
     { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_type_decl((yyvsp[0].type)));
 						  reg_type((yyvsp[0].type), (yyvsp[0].type)->name, current_namespace, 0);
 						}
-#line 2741 "parser.tab.c" /* yacc.c:1648  */
+#line 2736 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 22:
-#line 367 "parser.y" /* yacc.c:1648  */
+#line 365 "parser.y" /* yacc.c:1646  */
     { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_module((yyvsp[0].type))); }
-#line 2747 "parser.tab.c" /* yacc.c:1648  */
+#line 2742 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 23:
-#line 368 "parser.y" /* yacc.c:1648  */
+#line 366 "parser.y" /* yacc.c:1646  */
     { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), (yyvsp[0].statement)); }
-#line 2753 "parser.tab.c" /* yacc.c:1648  */
+#line 2748 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 24:
-#line 369 "parser.y" /* yacc.c:1648  */
+#line 367 "parser.y" /* yacc.c:1646  */
     { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_importlib((yyvsp[0].str))); }
-#line 2759 "parser.tab.c" /* yacc.c:1648  */
+#line 2754 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 25:
-#line 370 "parser.y" /* yacc.c:1648  */
+#line 368 "parser.y" /* yacc.c:1646  */
     { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), make_statement_library((yyvsp[0].typelib))); }
-#line 2765 "parser.tab.c" /* yacc.c:1648  */
+#line 2760 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 26:
-#line 373 "parser.y" /* yacc.c:1648  */
+#line 371 "parser.y" /* yacc.c:1646  */
     { (yyval.stmt_list) = NULL; }
-#line 2771 "parser.tab.c" /* yacc.c:1648  */
+#line 2766 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 27:
-#line 374 "parser.y" /* yacc.c:1648  */
+#line 372 "parser.y" /* yacc.c:1646  */
     { (yyval.stmt_list) = append_statement((yyvsp[-1].stmt_list), (yyvsp[0].statement)); }
-#line 2777 "parser.tab.c" /* yacc.c:1648  */
+#line 2772 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 30:
-#line 382 "parser.y" /* yacc.c:1648  */
+#line 380 "parser.y" /* yacc.c:1646  */
     { (yyval.statement) = make_statement_cppquote((yyvsp[0].str)); }
-#line 2783 "parser.tab.c" /* yacc.c:1648  */
+#line 2778 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 31:
-#line 383 "parser.y" /* yacc.c:1648  */
+#line 381 "parser.y" /* yacc.c:1646  */
     { (yyval.statement) = make_statement_type_decl((yyvsp[-1].type)); }
-#line 2789 "parser.tab.c" /* yacc.c:1648  */
+#line 2784 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 32:
-#line 384 "parser.y" /* yacc.c:1648  */
+#line 382 "parser.y" /* yacc.c:1646  */
     { (yyval.statement) = make_statement_declaration((yyvsp[-1].var)); }
-#line 2795 "parser.tab.c" /* yacc.c:1648  */
+#line 2790 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 33:
-#line 385 "parser.y" /* yacc.c:1648  */
+#line 383 "parser.y" /* yacc.c:1646  */
     { (yyval.statement) = make_statement_import((yyvsp[0].str)); }
-#line 2801 "parser.tab.c" /* yacc.c:1648  */
+#line 2796 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 34:
-#line 386 "parser.y" /* yacc.c:1648  */
+#line 384 "parser.y" /* yacc.c:1646  */
     { (yyval.statement) = (yyvsp[-1].statement); }
-#line 2807 "parser.tab.c" /* yacc.c:1648  */
+#line 2802 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 35:
-#line 387 "parser.y" /* yacc.c:1648  */
+#line 385 "parser.y" /* yacc.c:1646  */
     { (yyval.statement) = make_statement_pragma((yyvsp[0].str)); }
-#line 2813 "parser.tab.c" /* yacc.c:1648  */
+#line 2808 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 36:
-#line 388 "parser.y" /* yacc.c:1648  */
+#line 386 "parser.y" /* yacc.c:1646  */
     { (yyval.statement) = NULL; }
-#line 2819 "parser.tab.c" /* yacc.c:1648  */
+#line 2814 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 37:
-#line 392 "parser.y" /* yacc.c:1648  */
+#line 390 "parser.y" /* yacc.c:1646  */
     {
                       int result;
                       (yyval.statement) = NULL;
@@ -2827,909 +2822,909 @@ yyreduce:
                       if(!result)
                           error_loc("expected \"disable\" or \"enable\"\n");
                   }
-#line 2831 "parser.tab.c" /* yacc.c:1648  */
+#line 2826 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 38:
-#line 402 "parser.y" /* yacc.c:1648  */
+#line 400 "parser.y" /* yacc.c:1646  */
     { (yyval.warning_list) = append_warning(NULL, (yyvsp[0].num)); }
-#line 2837 "parser.tab.c" /* yacc.c:1648  */
+#line 2832 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 39:
-#line 403 "parser.y" /* yacc.c:1648  */
+#line 401 "parser.y" /* yacc.c:1646  */
     { (yyval.warning_list) = append_warning((yyvsp[-1].warning_list), (yyvsp[0].num)); }
-#line 2843 "parser.tab.c" /* yacc.c:1648  */
+#line 2838 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 41:
-#line 408 "parser.y" /* yacc.c:1648  */
+#line 406 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = type_new_enum((yyvsp[0].str), current_namespace, FALSE, NULL); }
-#line 2849 "parser.tab.c" /* yacc.c:1648  */
+#line 2844 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 43:
-#line 410 "parser.y" /* yacc.c:1648  */
+#line 408 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = type_new_struct((yyvsp[0].str), current_namespace, FALSE, NULL); }
-#line 2855 "parser.tab.c" /* yacc.c:1648  */
+#line 2850 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 45:
-#line 412 "parser.y" /* yacc.c:1648  */
+#line 410 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = type_new_nonencapsulated_union((yyvsp[0].str), FALSE, NULL); }
-#line 2861 "parser.tab.c" /* yacc.c:1648  */
+#line 2856 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 46:
-#line 413 "parser.y" /* yacc.c:1648  */
+#line 411 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = (yyvsp[0].type); (yyval.type)->attrs = check_enum_attrs((yyvsp[-1].attr_list)); }
-#line 2867 "parser.tab.c" /* yacc.c:1648  */
+#line 2862 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 47:
-#line 414 "parser.y" /* yacc.c:1648  */
+#line 412 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = (yyvsp[0].type); (yyval.type)->attrs = check_struct_attrs((yyvsp[-1].attr_list)); }
-#line 2873 "parser.tab.c" /* yacc.c:1648  */
+#line 2868 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 48:
-#line 415 "parser.y" /* yacc.c:1648  */
+#line 413 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = (yyvsp[0].type); (yyval.type)->attrs = check_union_attrs((yyvsp[-1].attr_list)); }
-#line 2879 "parser.tab.c" /* yacc.c:1648  */
+#line 2874 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 49:
-#line 418 "parser.y" /* yacc.c:1648  */
+#line 416 "parser.y" /* yacc.c:1646  */
     { (yyval.str) = (yyvsp[-1].str); }
-#line 2885 "parser.tab.c" /* yacc.c:1648  */
+#line 2880 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 50:
-#line 420 "parser.y" /* yacc.c:1648  */
+#line 418 "parser.y" /* yacc.c:1646  */
     { assert(yychar == YYEMPTY);
 						  (yyval.import) = xmalloc(sizeof(struct _import_t));
 						  (yyval.import)->name = (yyvsp[-1].str);
 						  (yyval.import)->import_performed = do_import((yyvsp[-1].str));
 						  if (!(yyval.import)->import_performed) yychar = aEOF;
 						}
-#line 2896 "parser.tab.c" /* yacc.c:1648  */
+#line 2891 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 51:
-#line 428 "parser.y" /* yacc.c:1648  */
+#line 426 "parser.y" /* yacc.c:1646  */
     { (yyval.str) = (yyvsp[-2].import)->name;
 						  if ((yyvsp[-2].import)->import_performed) pop_import();
 						  free((yyvsp[-2].import));
 						}
-#line 2905 "parser.tab.c" /* yacc.c:1648  */
+#line 2900 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 52:
-#line 435 "parser.y" /* yacc.c:1648  */
+#line 433 "parser.y" /* yacc.c:1646  */
     { (yyval.str) = (yyvsp[-2].str); if(!parse_only) add_importlib((yyvsp[-2].str), current_typelib); }
-#line 2911 "parser.tab.c" /* yacc.c:1648  */
+#line 2906 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 53:
-#line 438 "parser.y" /* yacc.c:1648  */
+#line 436 "parser.y" /* yacc.c:1646  */
     { (yyval.str) = (yyvsp[0].str); }
-#line 2917 "parser.tab.c" /* yacc.c:1648  */
+#line 2912 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 54:
-#line 439 "parser.y" /* yacc.c:1648  */
+#line 437 "parser.y" /* yacc.c:1646  */
     { (yyval.str) = (yyvsp[0].str); }
-#line 2923 "parser.tab.c" /* yacc.c:1648  */
+#line 2918 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 55:
-#line 441 "parser.y" /* yacc.c:1648  */
+#line 439 "parser.y" /* yacc.c:1646  */
     { (yyval.typelib) = make_library((yyvsp[-1].str), check_library_attrs((yyvsp[-1].str), (yyvsp[-2].attr_list)));
 						  if (!parse_only && do_typelib) current_typelib = (yyval.typelib);
 						}
-#line 2931 "parser.tab.c" /* yacc.c:1648  */
+#line 2926 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 56:
-#line 446 "parser.y" /* yacc.c:1648  */
+#line 444 "parser.y" /* yacc.c:1646  */
     { (yyval.typelib) = (yyvsp[-3].typelib); (yyval.typelib)->stmts = (yyvsp[-2].stmt_list); }
-#line 2937 "parser.tab.c" /* yacc.c:1648  */
+#line 2932 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 57:
-#line 449 "parser.y" /* yacc.c:1648  */
+#line 447 "parser.y" /* yacc.c:1646  */
     { (yyval.var_list) = NULL; }
-#line 2943 "parser.tab.c" /* yacc.c:1648  */
+#line 2938 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 59:
-#line 453 "parser.y" /* yacc.c:1648  */
+#line 451 "parser.y" /* yacc.c:1646  */
     { check_arg_attrs((yyvsp[0].var)); (yyval.var_list) = append_var( NULL, (yyvsp[0].var) ); }
-#line 2949 "parser.tab.c" /* yacc.c:1648  */
+#line 2944 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 60:
-#line 454 "parser.y" /* yacc.c:1648  */
+#line 452 "parser.y" /* yacc.c:1646  */
     { check_arg_attrs((yyvsp[0].var)); (yyval.var_list) = append_var( (yyvsp[-2].var_list), (yyvsp[0].var) ); }
-#line 2955 "parser.tab.c" /* yacc.c:1648  */
+#line 2950 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 62:
-#line 458 "parser.y" /* yacc.c:1648  */
+#line 456 "parser.y" /* yacc.c:1646  */
     { (yyval.var_list) = append_var( (yyvsp[-2].var_list), make_var(strdup("...")) ); }
-#line 2961 "parser.tab.c" /* yacc.c:1648  */
+#line 2956 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 63:
-#line 462 "parser.y" /* yacc.c:1648  */
+#line 460 "parser.y" /* yacc.c:1646  */
     { if ((yyvsp[-1].declspec)->stgclass != STG_NONE && (yyvsp[-1].declspec)->stgclass != STG_REGISTER)
 						    error_loc("invalid storage class for function parameter\n");
 						  (yyval.var) = declare_var((yyvsp[-2].attr_list), (yyvsp[-1].declspec), (yyvsp[0].declarator), TRUE);
 						  free((yyvsp[-1].declspec)); free((yyvsp[0].declarator));
 						}
-#line 2971 "parser.tab.c" /* yacc.c:1648  */
+#line 2966 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 64:
-#line 467 "parser.y" /* yacc.c:1648  */
+#line 465 "parser.y" /* yacc.c:1646  */
     { if ((yyvsp[-1].declspec)->stgclass != STG_NONE && (yyvsp[-1].declspec)->stgclass != STG_REGISTER)
 						    error_loc("invalid storage class for function parameter\n");
 						  (yyval.var) = declare_var(NULL, (yyvsp[-1].declspec), (yyvsp[0].declarator), TRUE);
 						  free((yyvsp[-1].declspec)); free((yyvsp[0].declarator));
 						}
-#line 2981 "parser.tab.c" /* yacc.c:1648  */
+#line 2976 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 65:
-#line 474 "parser.y" /* yacc.c:1648  */
+#line 472 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = (yyvsp[-1].expr);
 						  if (!(yyval.expr)->is_const || (yyval.expr)->cval <= 0)
 						      error_loc("array dimension is not a positive integer constant\n");
 						}
-#line 2990 "parser.tab.c" /* yacc.c:1648  */
+#line 2985 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 66:
-#line 478 "parser.y" /* yacc.c:1648  */
+#line 476 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr(EXPR_VOID); }
-#line 2996 "parser.tab.c" /* yacc.c:1648  */
+#line 2991 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 67:
-#line 479 "parser.y" /* yacc.c:1648  */
+#line 477 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr(EXPR_VOID); }
-#line 3002 "parser.tab.c" /* yacc.c:1648  */
+#line 2997 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 68:
-#line 482 "parser.y" /* yacc.c:1648  */
+#line 480 "parser.y" /* yacc.c:1646  */
     { (yyval.attr_list) = NULL; }
-#line 3008 "parser.tab.c" /* yacc.c:1648  */
+#line 3003 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 70:
-#line 487 "parser.y" /* yacc.c:1648  */
+#line 485 "parser.y" /* yacc.c:1646  */
     { (yyval.attr_list) = (yyvsp[-1].attr_list); }
-#line 3014 "parser.tab.c" /* yacc.c:1648  */
+#line 3009 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 71:
-#line 490 "parser.y" /* yacc.c:1648  */
+#line 488 "parser.y" /* yacc.c:1646  */
     { (yyval.attr_list) = append_attr( NULL, (yyvsp[0].attr) ); }
-#line 3020 "parser.tab.c" /* yacc.c:1648  */
+#line 3015 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 72:
-#line 491 "parser.y" /* yacc.c:1648  */
+#line 489 "parser.y" /* yacc.c:1646  */
     { (yyval.attr_list) = append_attr( (yyvsp[-2].attr_list), (yyvsp[0].attr) ); }
-#line 3026 "parser.tab.c" /* yacc.c:1648  */
+#line 3021 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 73:
-#line 492 "parser.y" /* yacc.c:1648  */
+#line 490 "parser.y" /* yacc.c:1646  */
     { (yyval.attr_list) = append_attr( (yyvsp[-3].attr_list), (yyvsp[0].attr) ); }
-#line 3032 "parser.tab.c" /* yacc.c:1648  */
+#line 3027 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 74:
-#line 495 "parser.y" /* yacc.c:1648  */
+#line 493 "parser.y" /* yacc.c:1646  */
     { (yyval.str_list) = append_str( NULL, (yyvsp[0].str) ); }
-#line 3038 "parser.tab.c" /* yacc.c:1648  */
+#line 3033 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 75:
-#line 496 "parser.y" /* yacc.c:1648  */
+#line 494 "parser.y" /* yacc.c:1646  */
     { (yyval.str_list) = append_str( (yyvsp[-2].str_list), (yyvsp[0].str) ); }
-#line 3044 "parser.tab.c" /* yacc.c:1648  */
+#line 3039 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 76:
-#line 499 "parser.y" /* yacc.c:1648  */
+#line 497 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = NULL; }
-#line 3050 "parser.tab.c" /* yacc.c:1648  */
+#line 3045 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 77:
-#line 500 "parser.y" /* yacc.c:1648  */
+#line 498 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_AGGREGATABLE); }
-#line 3056 "parser.tab.c" /* yacc.c:1648  */
+#line 3051 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 78:
-#line 501 "parser.y" /* yacc.c:1648  */
+#line 499 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrp(ATTR_ANNOTATION, (yyvsp[-1].str)); }
-#line 3062 "parser.tab.c" /* yacc.c:1648  */
+#line 3057 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 79:
-#line 502 "parser.y" /* yacc.c:1648  */
+#line 500 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_APPOBJECT); }
-#line 3068 "parser.tab.c" /* yacc.c:1648  */
+#line 3063 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 80:
-#line 503 "parser.y" /* yacc.c:1648  */
+#line 501 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_ASYNC); }
-#line 3074 "parser.tab.c" /* yacc.c:1648  */
+#line 3069 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 81:
-#line 504 "parser.y" /* yacc.c:1648  */
+#line 502 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_AUTO_HANDLE); }
-#line 3080 "parser.tab.c" /* yacc.c:1648  */
+#line 3075 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 82:
-#line 505 "parser.y" /* yacc.c:1648  */
+#line 503 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_BINDABLE); }
-#line 3086 "parser.tab.c" /* yacc.c:1648  */
+#line 3081 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 83:
-#line 506 "parser.y" /* yacc.c:1648  */
+#line 504 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_BROADCAST); }
-#line 3092 "parser.tab.c" /* yacc.c:1648  */
+#line 3087 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 84:
-#line 507 "parser.y" /* yacc.c:1648  */
+#line 505 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrp(ATTR_CALLAS, (yyvsp[-1].var)); }
-#line 3098 "parser.tab.c" /* yacc.c:1648  */
+#line 3093 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 85:
-#line 508 "parser.y" /* yacc.c:1648  */
+#line 506 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrp(ATTR_CASE, (yyvsp[-1].expr_list)); }
-#line 3104 "parser.tab.c" /* yacc.c:1648  */
+#line 3099 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 86:
-#line 509 "parser.y" /* yacc.c:1648  */
+#line 507 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_CODE); }
-#line 3110 "parser.tab.c" /* yacc.c:1648  */
+#line 3105 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 87:
-#line 510 "parser.y" /* yacc.c:1648  */
+#line 508 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_COMMSTATUS); }
-#line 3116 "parser.tab.c" /* yacc.c:1648  */
+#line 3111 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 88:
-#line 511 "parser.y" /* yacc.c:1648  */
+#line 509 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrv(ATTR_CONTEXTHANDLE, 0); }
-#line 3122 "parser.tab.c" /* yacc.c:1648  */
+#line 3117 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 89:
-#line 512 "parser.y" /* yacc.c:1648  */
+#line 510 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_DONT_SERIALIZE */ }
-#line 3128 "parser.tab.c" /* yacc.c:1648  */
+#line 3123 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 90:
-#line 513 "parser.y" /* yacc.c:1648  */
+#line 511 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_SERIALIZE */ }
-#line 3134 "parser.tab.c" /* yacc.c:1648  */
+#line 3129 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 91:
-#line 514 "parser.y" /* yacc.c:1648  */
+#line 512 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_CONTROL); }
-#line 3140 "parser.tab.c" /* yacc.c:1648  */
+#line 3135 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 92:
-#line 515 "parser.y" /* yacc.c:1648  */
+#line 513 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_DECODE); }
-#line 3146 "parser.tab.c" /* yacc.c:1648  */
+#line 3141 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 93:
-#line 516 "parser.y" /* yacc.c:1648  */
+#line 514 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_DEFAULT); }
-#line 3152 "parser.tab.c" /* yacc.c:1648  */
+#line 3147 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 94:
-#line 517 "parser.y" /* yacc.c:1648  */
+#line 515 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_DEFAULTBIND); }
-#line 3158 "parser.tab.c" /* yacc.c:1648  */
+#line 3153 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 95:
-#line 518 "parser.y" /* yacc.c:1648  */
+#line 516 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_DEFAULTCOLLELEM); }
-#line 3164 "parser.tab.c" /* yacc.c:1648  */
+#line 3159 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 96:
-#line 519 "parser.y" /* yacc.c:1648  */
+#line 517 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrp(ATTR_DEFAULTVALUE, (yyvsp[-1].expr)); }
-#line 3170 "parser.tab.c" /* yacc.c:1648  */
+#line 3165 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 97:
-#line 520 "parser.y" /* yacc.c:1648  */
+#line 518 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_DEFAULTVTABLE); }
-#line 3176 "parser.tab.c" /* yacc.c:1648  */
+#line 3171 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 98:
-#line 521 "parser.y" /* yacc.c:1648  */
+#line 519 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_DISABLECONSISTENCYCHECK); }
-#line 3182 "parser.tab.c" /* yacc.c:1648  */
+#line 3177 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 99:
-#line 522 "parser.y" /* yacc.c:1648  */
+#line 520 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_DISPLAYBIND); }
-#line 3188 "parser.tab.c" /* yacc.c:1648  */
+#line 3183 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 100:
-#line 523 "parser.y" /* yacc.c:1648  */
+#line 521 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrp(ATTR_DLLNAME, (yyvsp[-1].str)); }
-#line 3194 "parser.tab.c" /* yacc.c:1648  */
+#line 3189 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 101:
-#line 524 "parser.y" /* yacc.c:1648  */
+#line 522 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_DUAL); }
-#line 3200 "parser.tab.c" /* yacc.c:1648  */
+#line 3195 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 102:
-#line 525 "parser.y" /* yacc.c:1648  */
+#line 523 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_ENABLEALLOCATE); }
-#line 3206 "parser.tab.c" /* yacc.c:1648  */
+#line 3201 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 103:
-#line 526 "parser.y" /* yacc.c:1648  */
+#line 524 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_ENCODE); }
-#line 3212 "parser.tab.c" /* yacc.c:1648  */
+#line 3207 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 104:
-#line 527 "parser.y" /* yacc.c:1648  */
+#line 525 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrp(ATTR_ENDPOINT, (yyvsp[-1].str_list)); }
-#line 3218 "parser.tab.c" /* yacc.c:1648  */
+#line 3213 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 105:
-#line 528 "parser.y" /* yacc.c:1648  */
+#line 526 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrp(ATTR_ENTRY, (yyvsp[-1].expr)); }
-#line 3224 "parser.tab.c" /* yacc.c:1648  */
+#line 3219 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 106:
-#line 529 "parser.y" /* yacc.c:1648  */
+#line 527 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_EXPLICIT_HANDLE); }
-#line 3230 "parser.tab.c" /* yacc.c:1648  */
+#line 3225 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 107:
-#line 530 "parser.y" /* yacc.c:1648  */
+#line 528 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_FAULTSTATUS); }
-#line 3236 "parser.tab.c" /* yacc.c:1648  */
+#line 3231 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 108:
-#line 531 "parser.y" /* yacc.c:1648  */
+#line 529 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_FORCEALLOCATE); }
-#line 3242 "parser.tab.c" /* yacc.c:1648  */
+#line 3237 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 109:
-#line 532 "parser.y" /* yacc.c:1648  */
+#line 530 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_HANDLE); }
-#line 3248 "parser.tab.c" /* yacc.c:1648  */
+#line 3243 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 110:
-#line 533 "parser.y" /* yacc.c:1648  */
+#line 531 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrp(ATTR_HELPCONTEXT, (yyvsp[-1].expr)); }
-#line 3254 "parser.tab.c" /* yacc.c:1648  */
+#line 3249 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 111:
-#line 534 "parser.y" /* yacc.c:1648  */
+#line 532 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrp(ATTR_HELPFILE, (yyvsp[-1].str)); }
-#line 3260 "parser.tab.c" /* yacc.c:1648  */
+#line 3255 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 112:
-#line 535 "parser.y" /* yacc.c:1648  */
+#line 533 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrp(ATTR_HELPSTRING, (yyvsp[-1].str)); }
-#line 3266 "parser.tab.c" /* yacc.c:1648  */
+#line 3261 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 113:
-#line 536 "parser.y" /* yacc.c:1648  */
+#line 534 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrp(ATTR_HELPSTRINGCONTEXT, (yyvsp[-1].expr)); }
-#line 3272 "parser.tab.c" /* yacc.c:1648  */
+#line 3267 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 114:
-#line 537 "parser.y" /* yacc.c:1648  */
+#line 535 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrp(ATTR_HELPSTRINGDLL, (yyvsp[-1].str)); }
-#line 3278 "parser.tab.c" /* yacc.c:1648  */
+#line 3273 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 115:
-#line 538 "parser.y" /* yacc.c:1648  */
+#line 536 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_HIDDEN); }
-#line 3284 "parser.tab.c" /* yacc.c:1648  */
+#line 3279 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 116:
-#line 539 "parser.y" /* yacc.c:1648  */
+#line 537 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrp(ATTR_ID, (yyvsp[-1].expr)); }
-#line 3290 "parser.tab.c" /* yacc.c:1648  */
+#line 3285 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 117:
-#line 540 "parser.y" /* yacc.c:1648  */
+#line 538 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_IDEMPOTENT); }
-#line 3296 "parser.tab.c" /* yacc.c:1648  */
+#line 3291 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 118:
-#line 541 "parser.y" /* yacc.c:1648  */
+#line 539 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_IGNORE); }
-#line 3302 "parser.tab.c" /* yacc.c:1648  */
+#line 3297 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 119:
-#line 542 "parser.y" /* yacc.c:1648  */
+#line 540 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrp(ATTR_IIDIS, (yyvsp[-1].expr)); }
-#line 3308 "parser.tab.c" /* yacc.c:1648  */
+#line 3303 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 120:
-#line 543 "parser.y" /* yacc.c:1648  */
+#line 541 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_IMMEDIATEBIND); }
-#line 3314 "parser.tab.c" /* yacc.c:1648  */
+#line 3309 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 121:
-#line 544 "parser.y" /* yacc.c:1648  */
+#line 542 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrp(ATTR_IMPLICIT_HANDLE, (yyvsp[-1].var)); }
-#line 3320 "parser.tab.c" /* yacc.c:1648  */
+#line 3315 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 122:
-#line 545 "parser.y" /* yacc.c:1648  */
+#line 543 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_IN); }
-#line 3326 "parser.tab.c" /* yacc.c:1648  */
+#line 3321 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 123:
-#line 546 "parser.y" /* yacc.c:1648  */
+#line 544 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_INPUTSYNC); }
-#line 3332 "parser.tab.c" /* yacc.c:1648  */
+#line 3327 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 124:
-#line 547 "parser.y" /* yacc.c:1648  */
+#line 545 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrp(ATTR_LENGTHIS, (yyvsp[-1].expr_list)); }
-#line 3338 "parser.tab.c" /* yacc.c:1648  */
+#line 3333 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 125:
-#line 548 "parser.y" /* yacc.c:1648  */
+#line 546 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrp(ATTR_LIBLCID, (yyvsp[-1].expr)); }
-#line 3344 "parser.tab.c" /* yacc.c:1648  */
+#line 3339 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 126:
-#line 549 "parser.y" /* yacc.c:1648  */
+#line 547 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_PARAMLCID); }
-#line 3350 "parser.tab.c" /* yacc.c:1648  */
+#line 3345 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 127:
-#line 550 "parser.y" /* yacc.c:1648  */
+#line 548 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_LICENSED); }
-#line 3356 "parser.tab.c" /* yacc.c:1648  */
+#line 3351 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 128:
-#line 551 "parser.y" /* yacc.c:1648  */
+#line 549 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_LOCAL); }
-#line 3362 "parser.tab.c" /* yacc.c:1648  */
+#line 3357 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 129:
-#line 552 "parser.y" /* yacc.c:1648  */
+#line 550 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_MAYBE); }
-#line 3368 "parser.tab.c" /* yacc.c:1648  */
+#line 3363 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 130:
-#line 553 "parser.y" /* yacc.c:1648  */
+#line 551 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_MESSAGE); }
-#line 3374 "parser.tab.c" /* yacc.c:1648  */
+#line 3369 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 131:
-#line 554 "parser.y" /* yacc.c:1648  */
+#line 552 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_NOCODE); }
-#line 3380 "parser.tab.c" /* yacc.c:1648  */
+#line 3375 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 132:
-#line 555 "parser.y" /* yacc.c:1648  */
+#line 553 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_NONBROWSABLE); }
-#line 3386 "parser.tab.c" /* yacc.c:1648  */
+#line 3381 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 133:
-#line 556 "parser.y" /* yacc.c:1648  */
+#line 554 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_NONCREATABLE); }
-#line 3392 "parser.tab.c" /* yacc.c:1648  */
+#line 3387 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 134:
-#line 557 "parser.y" /* yacc.c:1648  */
+#line 555 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_NONEXTENSIBLE); }
-#line 3398 "parser.tab.c" /* yacc.c:1648  */
+#line 3393 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 135:
-#line 558 "parser.y" /* yacc.c:1648  */
+#line 556 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_NOTIFY); }
-#line 3404 "parser.tab.c" /* yacc.c:1648  */
+#line 3399 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 136:
-#line 559 "parser.y" /* yacc.c:1648  */
+#line 557 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_NOTIFYFLAG); }
-#line 3410 "parser.tab.c" /* yacc.c:1648  */
+#line 3405 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 137:
-#line 560 "parser.y" /* yacc.c:1648  */
+#line 558 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_OBJECT); }
-#line 3416 "parser.tab.c" /* yacc.c:1648  */
+#line 3411 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 138:
-#line 561 "parser.y" /* yacc.c:1648  */
+#line 559 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_ODL); }
-#line 3422 "parser.tab.c" /* yacc.c:1648  */
+#line 3417 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 139:
-#line 562 "parser.y" /* yacc.c:1648  */
+#line 560 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_OLEAUTOMATION); }
-#line 3428 "parser.tab.c" /* yacc.c:1648  */
+#line 3423 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 140:
-#line 563 "parser.y" /* yacc.c:1648  */
+#line 561 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrp(ATTR_OPTIMIZE, (yyvsp[-1].str)); }
-#line 3434 "parser.tab.c" /* yacc.c:1648  */
+#line 3429 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 141:
-#line 564 "parser.y" /* yacc.c:1648  */
+#line 562 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_OPTIONAL); }
-#line 3440 "parser.tab.c" /* yacc.c:1648  */
+#line 3435 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 142:
-#line 565 "parser.y" /* yacc.c:1648  */
+#line 563 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_OUT); }
-#line 3446 "parser.tab.c" /* yacc.c:1648  */
+#line 3441 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 143:
-#line 566 "parser.y" /* yacc.c:1648  */
+#line 564 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_PARTIALIGNORE); }
-#line 3452 "parser.tab.c" /* yacc.c:1648  */
+#line 3447 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 144:
-#line 567 "parser.y" /* yacc.c:1648  */
+#line 565 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrv(ATTR_POINTERDEFAULT, (yyvsp[-1].num)); }
-#line 3458 "parser.tab.c" /* yacc.c:1648  */
+#line 3453 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 145:
-#line 568 "parser.y" /* yacc.c:1648  */
+#line 566 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrp(ATTR_PROGID, (yyvsp[-1].str)); }
-#line 3464 "parser.tab.c" /* yacc.c:1648  */
+#line 3459 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 146:
-#line 569 "parser.y" /* yacc.c:1648  */
+#line 567 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_PROPGET); }
-#line 3470 "parser.tab.c" /* yacc.c:1648  */
+#line 3465 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 147:
-#line 570 "parser.y" /* yacc.c:1648  */
+#line 568 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_PROPPUT); }
-#line 3476 "parser.tab.c" /* yacc.c:1648  */
+#line 3471 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 148:
-#line 571 "parser.y" /* yacc.c:1648  */
+#line 569 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_PROPPUTREF); }
-#line 3482 "parser.tab.c" /* yacc.c:1648  */
+#line 3477 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 149:
-#line 572 "parser.y" /* yacc.c:1648  */
+#line 570 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_PROXY); }
-#line 3488 "parser.tab.c" /* yacc.c:1648  */
+#line 3483 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 150:
-#line 573 "parser.y" /* yacc.c:1648  */
+#line 571 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_PUBLIC); }
-#line 3494 "parser.tab.c" /* yacc.c:1648  */
+#line 3489 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 151:
-#line 575 "parser.y" /* yacc.c:1648  */
+#line 573 "parser.y" /* yacc.c:1646  */
     { expr_list_t *list = append_expr( NULL, (yyvsp[-3].expr) );
 						  list = append_expr( list, (yyvsp[-1].expr) );
 						  (yyval.attr) = make_attrp(ATTR_RANGE, list); }
-#line 3502 "parser.tab.c" /* yacc.c:1648  */
+#line 3497 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 152:
-#line 578 "parser.y" /* yacc.c:1648  */
+#line 576 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_READONLY); }
-#line 3508 "parser.tab.c" /* yacc.c:1648  */
+#line 3503 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 153:
-#line 579 "parser.y" /* yacc.c:1648  */
+#line 577 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrp(ATTR_REPRESENTAS, (yyvsp[-1].type)); }
-#line 3514 "parser.tab.c" /* yacc.c:1648  */
+#line 3509 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 154:
-#line 580 "parser.y" /* yacc.c:1648  */
+#line 578 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_REQUESTEDIT); }
-#line 3520 "parser.tab.c" /* yacc.c:1648  */
+#line 3515 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 155:
-#line 581 "parser.y" /* yacc.c:1648  */
+#line 579 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_RESTRICTED); }
-#line 3526 "parser.tab.c" /* yacc.c:1648  */
+#line 3521 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 156:
-#line 582 "parser.y" /* yacc.c:1648  */
+#line 580 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_RETVAL); }
-#line 3532 "parser.tab.c" /* yacc.c:1648  */
+#line 3527 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 157:
-#line 583 "parser.y" /* yacc.c:1648  */
+#line 581 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrp(ATTR_SIZEIS, (yyvsp[-1].expr_list)); }
-#line 3538 "parser.tab.c" /* yacc.c:1648  */
+#line 3533 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 158:
-#line 584 "parser.y" /* yacc.c:1648  */
+#line 582 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_SOURCE); }
-#line 3544 "parser.tab.c" /* yacc.c:1648  */
+#line 3539 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 159:
-#line 585 "parser.y" /* yacc.c:1648  */
+#line 583 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_STRICTCONTEXTHANDLE); }
-#line 3550 "parser.tab.c" /* yacc.c:1648  */
+#line 3545 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 160:
-#line 586 "parser.y" /* yacc.c:1648  */
+#line 584 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_STRING); }
-#line 3556 "parser.tab.c" /* yacc.c:1648  */
+#line 3551 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 161:
-#line 587 "parser.y" /* yacc.c:1648  */
+#line 585 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrp(ATTR_SWITCHIS, (yyvsp[-1].expr)); }
-#line 3562 "parser.tab.c" /* yacc.c:1648  */
+#line 3557 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 162:
-#line 588 "parser.y" /* yacc.c:1648  */
+#line 586 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrp(ATTR_SWITCHTYPE, (yyvsp[-1].type)); }
-#line 3568 "parser.tab.c" /* yacc.c:1648  */
+#line 3563 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 163:
-#line 589 "parser.y" /* yacc.c:1648  */
+#line 587 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrp(ATTR_TRANSMITAS, (yyvsp[-1].type)); }
-#line 3574 "parser.tab.c" /* yacc.c:1648  */
+#line 3569 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 164:
-#line 590 "parser.y" /* yacc.c:1648  */
+#line 588 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrv(ATTR_THREADING, (yyvsp[-1].num)); }
-#line 3580 "parser.tab.c" /* yacc.c:1648  */
+#line 3575 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 165:
-#line 591 "parser.y" /* yacc.c:1648  */
+#line 589 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_UIDEFAULT); }
-#line 3586 "parser.tab.c" /* yacc.c:1648  */
+#line 3581 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 166:
-#line 592 "parser.y" /* yacc.c:1648  */
+#line 590 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_USESGETLASTERROR); }
-#line 3592 "parser.tab.c" /* yacc.c:1648  */
+#line 3587 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 167:
-#line 593 "parser.y" /* yacc.c:1648  */
+#line 591 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrp(ATTR_USERMARSHAL, (yyvsp[-1].type)); }
-#line 3598 "parser.tab.c" /* yacc.c:1648  */
+#line 3593 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 168:
-#line 594 "parser.y" /* yacc.c:1648  */
+#line 592 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrp(ATTR_UUID, (yyvsp[-1].uuid)); }
-#line 3604 "parser.tab.c" /* yacc.c:1648  */
+#line 3599 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 169:
-#line 595 "parser.y" /* yacc.c:1648  */
+#line 593 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrp(ATTR_ASYNCUUID, (yyvsp[-1].uuid)); }
-#line 3610 "parser.tab.c" /* yacc.c:1648  */
+#line 3605 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 170:
-#line 596 "parser.y" /* yacc.c:1648  */
+#line 594 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_V1ENUM); }
-#line 3616 "parser.tab.c" /* yacc.c:1648  */
+#line 3611 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 171:
-#line 597 "parser.y" /* yacc.c:1648  */
+#line 595 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_VARARG); }
-#line 3622 "parser.tab.c" /* yacc.c:1648  */
+#line 3617 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 172:
-#line 598 "parser.y" /* yacc.c:1648  */
+#line 596 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrv(ATTR_VERSION, (yyvsp[-1].num)); }
-#line 3628 "parser.tab.c" /* yacc.c:1648  */
+#line 3623 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 173:
-#line 599 "parser.y" /* yacc.c:1648  */
+#line 597 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrp(ATTR_VIPROGID, (yyvsp[-1].str)); }
-#line 3634 "parser.tab.c" /* yacc.c:1648  */
+#line 3629 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 174:
-#line 600 "parser.y" /* yacc.c:1648  */
+#line 598 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrp(ATTR_WIREMARSHAL, (yyvsp[-1].type)); }
-#line 3640 "parser.tab.c" /* yacc.c:1648  */
+#line 3635 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 175:
-#line 601 "parser.y" /* yacc.c:1648  */
+#line 599 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attrv(ATTR_POINTERTYPE, (yyvsp[0].num)); }
-#line 3646 "parser.tab.c" /* yacc.c:1648  */
+#line 3641 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 177:
-#line 606 "parser.y" /* yacc.c:1648  */
+#line 604 "parser.y" /* yacc.c:1646  */
     { if (!is_valid_uuid((yyvsp[0].str)))
 						    error_loc("invalid UUID: %s\n", (yyvsp[0].str));
 						  (yyval.uuid) = parse_uuid((yyvsp[0].str)); }
-#line 3654 "parser.tab.c" /* yacc.c:1648  */
+#line 3649 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 178:
-#line 611 "parser.y" /* yacc.c:1648  */
+#line 609 "parser.y" /* yacc.c:1646  */
     { (yyval.str) = xstrdup("__cdecl"); }
-#line 3660 "parser.tab.c" /* yacc.c:1648  */
+#line 3655 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 179:
-#line 612 "parser.y" /* yacc.c:1648  */
+#line 610 "parser.y" /* yacc.c:1646  */
     { (yyval.str) = xstrdup("__fastcall"); }
-#line 3666 "parser.tab.c" /* yacc.c:1648  */
+#line 3661 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 180:
-#line 613 "parser.y" /* yacc.c:1648  */
+#line 611 "parser.y" /* yacc.c:1646  */
     { (yyval.str) = xstrdup("__pascal"); }
-#line 3672 "parser.tab.c" /* yacc.c:1648  */
+#line 3667 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 181:
-#line 614 "parser.y" /* yacc.c:1648  */
+#line 612 "parser.y" /* yacc.c:1646  */
     { (yyval.str) = xstrdup("__stdcall"); }
-#line 3678 "parser.tab.c" /* yacc.c:1648  */
+#line 3673 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 182:
-#line 617 "parser.y" /* yacc.c:1648  */
+#line 615 "parser.y" /* yacc.c:1646  */
     { (yyval.var_list) = NULL; }
-#line 3684 "parser.tab.c" /* yacc.c:1648  */
+#line 3679 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 183:
-#line 618 "parser.y" /* yacc.c:1648  */
+#line 616 "parser.y" /* yacc.c:1646  */
     { (yyval.var_list) = append_var( (yyvsp[-1].var_list), (yyvsp[0].var) ); }
-#line 3690 "parser.tab.c" /* yacc.c:1648  */
+#line 3685 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 184:
-#line 621 "parser.y" /* yacc.c:1648  */
+#line 619 "parser.y" /* yacc.c:1646  */
     { attr_t *a = make_attrp(ATTR_CASE, append_expr( NULL, (yyvsp[-2].expr) ));
 						  (yyval.var) = (yyvsp[0].var); if (!(yyval.var)) (yyval.var) = make_var(NULL);
 						  (yyval.var)->attrs = append_attr( (yyval.var)->attrs, a );
 						}
-#line 3699 "parser.tab.c" /* yacc.c:1648  */
+#line 3694 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 185:
-#line 625 "parser.y" /* yacc.c:1648  */
+#line 623 "parser.y" /* yacc.c:1646  */
     { attr_t *a = make_attr(ATTR_DEFAULT);
 						  (yyval.var) = (yyvsp[0].var); if (!(yyval.var)) (yyval.var) = make_var(NULL);
 						  (yyval.var)->attrs = append_attr( (yyval.var)->attrs, a );
 						}
-#line 3708 "parser.tab.c" /* yacc.c:1648  */
+#line 3703 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 186:
-#line 631 "parser.y" /* yacc.c:1648  */
+#line 629 "parser.y" /* yacc.c:1646  */
     { (yyval.var_list) = NULL; }
-#line 3714 "parser.tab.c" /* yacc.c:1648  */
+#line 3709 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 187:
-#line 632 "parser.y" /* yacc.c:1648  */
+#line 630 "parser.y" /* yacc.c:1646  */
     { (yyval.var_list) = (yyvsp[-1].var_list); }
-#line 3720 "parser.tab.c" /* yacc.c:1648  */
+#line 3715 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 189:
-#line 636 "parser.y" /* yacc.c:1648  */
+#line 634 "parser.y" /* yacc.c:1646  */
     { if (!(yyvsp[0].var)->eval)
 						    (yyvsp[0].var)->eval = make_exprl(EXPR_NUM, 0 /* default for first enum entry */);
                                                   (yyval.var_list) = append_var( NULL, (yyvsp[0].var) );
 						}
-#line 3729 "parser.tab.c" /* yacc.c:1648  */
+#line 3724 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 190:
-#line 640 "parser.y" /* yacc.c:1648  */
+#line 638 "parser.y" /* yacc.c:1646  */
     { if (!(yyvsp[0].var)->eval)
                                                   {
                                                     var_t *last = LIST_ENTRY( list_tail((yyval.var_list)), var_t, entry );
@@ -3740,656 +3735,656 @@ yyreduce:
                                                   }
                                                   (yyval.var_list) = append_var( (yyvsp[-2].var_list), (yyvsp[0].var) );
 						}
-#line 3744 "parser.tab.c" /* yacc.c:1648  */
+#line 3739 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 191:
-#line 652 "parser.y" /* yacc.c:1648  */
+#line 650 "parser.y" /* yacc.c:1646  */
     { (yyval.var) = reg_const((yyvsp[-2].var));
 						  (yyval.var)->eval = (yyvsp[0].expr);
-                                                  (yyval.var)->type = type_new_int(TYPE_BASIC_INT, 0);
+                                                  (yyval.var)->declspec.type = type_new_int(TYPE_BASIC_INT, 0);
 						}
-#line 3753 "parser.tab.c" /* yacc.c:1648  */
+#line 3748 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 192:
-#line 656 "parser.y" /* yacc.c:1648  */
+#line 654 "parser.y" /* yacc.c:1646  */
     { (yyval.var) = reg_const((yyvsp[0].var));
-                                                  (yyval.var)->type = type_new_int(TYPE_BASIC_INT, 0);
+                                                  (yyval.var)->declspec.type = type_new_int(TYPE_BASIC_INT, 0);
 						}
-#line 3761 "parser.tab.c" /* yacc.c:1648  */
+#line 3756 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 193:
-#line 661 "parser.y" /* yacc.c:1648  */
+#line 659 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = type_new_enum((yyvsp[-3].str), current_namespace, TRUE, (yyvsp[-1].var_list)); }
-#line 3767 "parser.tab.c" /* yacc.c:1648  */
+#line 3762 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 194:
-#line 664 "parser.y" /* yacc.c:1648  */
+#line 662 "parser.y" /* yacc.c:1646  */
     { (yyval.expr_list) = append_expr( NULL, (yyvsp[0].expr) ); }
-#line 3773 "parser.tab.c" /* yacc.c:1648  */
+#line 3768 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 195:
-#line 665 "parser.y" /* yacc.c:1648  */
+#line 663 "parser.y" /* yacc.c:1646  */
     { (yyval.expr_list) = append_expr( (yyvsp[-2].expr_list), (yyvsp[0].expr) ); }
-#line 3779 "parser.tab.c" /* yacc.c:1648  */
+#line 3774 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 196:
-#line 668 "parser.y" /* yacc.c:1648  */
+#line 666 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr(EXPR_VOID); }
-#line 3785 "parser.tab.c" /* yacc.c:1648  */
+#line 3780 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 198:
-#line 672 "parser.y" /* yacc.c:1648  */
+#line 670 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_exprl(EXPR_NUM, (yyvsp[0].num)); }
-#line 3791 "parser.tab.c" /* yacc.c:1648  */
+#line 3786 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 199:
-#line 673 "parser.y" /* yacc.c:1648  */
+#line 671 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_exprl(EXPR_HEXNUM, (yyvsp[0].num)); }
-#line 3797 "parser.tab.c" /* yacc.c:1648  */
+#line 3792 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 200:
-#line 674 "parser.y" /* yacc.c:1648  */
+#line 672 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_exprd(EXPR_DOUBLE, (yyvsp[0].dbl)); }
-#line 3803 "parser.tab.c" /* yacc.c:1648  */
+#line 3798 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 201:
-#line 675 "parser.y" /* yacc.c:1648  */
+#line 673 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_exprl(EXPR_TRUEFALSE, 0); }
-#line 3809 "parser.tab.c" /* yacc.c:1648  */
+#line 3804 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 202:
-#line 676 "parser.y" /* yacc.c:1648  */
+#line 674 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_exprl(EXPR_NUM, 0); }
-#line 3815 "parser.tab.c" /* yacc.c:1648  */
+#line 3810 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 203:
-#line 677 "parser.y" /* yacc.c:1648  */
+#line 675 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_exprl(EXPR_TRUEFALSE, 1); }
-#line 3821 "parser.tab.c" /* yacc.c:1648  */
+#line 3816 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 204:
-#line 678 "parser.y" /* yacc.c:1648  */
+#line 676 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_exprs(EXPR_STRLIT, (yyvsp[0].str)); }
-#line 3827 "parser.tab.c" /* yacc.c:1648  */
+#line 3822 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 205:
-#line 679 "parser.y" /* yacc.c:1648  */
+#line 677 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_exprs(EXPR_WSTRLIT, (yyvsp[0].str)); }
-#line 3833 "parser.tab.c" /* yacc.c:1648  */
+#line 3828 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 206:
-#line 680 "parser.y" /* yacc.c:1648  */
+#line 678 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_exprs(EXPR_CHARCONST, (yyvsp[0].str)); }
-#line 3839 "parser.tab.c" /* yacc.c:1648  */
+#line 3834 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 207:
-#line 681 "parser.y" /* yacc.c:1648  */
+#line 679 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_exprs(EXPR_IDENTIFIER, (yyvsp[0].str)); }
-#line 3845 "parser.tab.c" /* yacc.c:1648  */
+#line 3840 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 208:
-#line 682 "parser.y" /* yacc.c:1648  */
+#line 680 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr3(EXPR_COND, (yyvsp[-4].expr), (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 3851 "parser.tab.c" /* yacc.c:1648  */
+#line 3846 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 209:
-#line 683 "parser.y" /* yacc.c:1648  */
+#line 681 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr2(EXPR_LOGOR, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 3857 "parser.tab.c" /* yacc.c:1648  */
+#line 3852 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 210:
-#line 684 "parser.y" /* yacc.c:1648  */
+#line 682 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr2(EXPR_LOGAND, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 3863 "parser.tab.c" /* yacc.c:1648  */
+#line 3858 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 211:
-#line 685 "parser.y" /* yacc.c:1648  */
+#line 683 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr2(EXPR_OR , (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 3869 "parser.tab.c" /* yacc.c:1648  */
+#line 3864 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 212:
-#line 686 "parser.y" /* yacc.c:1648  */
+#line 684 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr2(EXPR_XOR, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 3875 "parser.tab.c" /* yacc.c:1648  */
+#line 3870 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 213:
-#line 687 "parser.y" /* yacc.c:1648  */
+#line 685 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr2(EXPR_AND, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 3881 "parser.tab.c" /* yacc.c:1648  */
+#line 3876 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 214:
-#line 688 "parser.y" /* yacc.c:1648  */
+#line 686 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr2(EXPR_EQUALITY, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 3887 "parser.tab.c" /* yacc.c:1648  */
+#line 3882 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 215:
-#line 689 "parser.y" /* yacc.c:1648  */
+#line 687 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr2(EXPR_INEQUALITY, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 3893 "parser.tab.c" /* yacc.c:1648  */
+#line 3888 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 216:
-#line 690 "parser.y" /* yacc.c:1648  */
+#line 688 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr2(EXPR_GTR, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 3899 "parser.tab.c" /* yacc.c:1648  */
+#line 3894 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 217:
-#line 691 "parser.y" /* yacc.c:1648  */
+#line 689 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr2(EXPR_LESS, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 3905 "parser.tab.c" /* yacc.c:1648  */
+#line 3900 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 218:
-#line 692 "parser.y" /* yacc.c:1648  */
+#line 690 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr2(EXPR_GTREQL, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 3911 "parser.tab.c" /* yacc.c:1648  */
+#line 3906 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 219:
-#line 693 "parser.y" /* yacc.c:1648  */
+#line 691 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr2(EXPR_LESSEQL, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 3917 "parser.tab.c" /* yacc.c:1648  */
+#line 3912 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 220:
-#line 694 "parser.y" /* yacc.c:1648  */
+#line 692 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr2(EXPR_SHL, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 3923 "parser.tab.c" /* yacc.c:1648  */
+#line 3918 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 221:
-#line 695 "parser.y" /* yacc.c:1648  */
+#line 693 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr2(EXPR_SHR, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 3929 "parser.tab.c" /* yacc.c:1648  */
+#line 3924 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 222:
-#line 696 "parser.y" /* yacc.c:1648  */
+#line 694 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr2(EXPR_ADD, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 3935 "parser.tab.c" /* yacc.c:1648  */
+#line 3930 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 223:
-#line 697 "parser.y" /* yacc.c:1648  */
+#line 695 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr2(EXPR_SUB, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 3941 "parser.tab.c" /* yacc.c:1648  */
+#line 3936 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 224:
-#line 698 "parser.y" /* yacc.c:1648  */
+#line 696 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr2(EXPR_MOD, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 3947 "parser.tab.c" /* yacc.c:1648  */
+#line 3942 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 225:
-#line 699 "parser.y" /* yacc.c:1648  */
+#line 697 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr2(EXPR_MUL, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 3953 "parser.tab.c" /* yacc.c:1648  */
+#line 3948 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 226:
-#line 700 "parser.y" /* yacc.c:1648  */
+#line 698 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr2(EXPR_DIV, (yyvsp[-2].expr), (yyvsp[0].expr)); }
-#line 3959 "parser.tab.c" /* yacc.c:1648  */
+#line 3954 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 227:
-#line 701 "parser.y" /* yacc.c:1648  */
+#line 699 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr1(EXPR_LOGNOT, (yyvsp[0].expr)); }
-#line 3965 "parser.tab.c" /* yacc.c:1648  */
+#line 3960 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 228:
-#line 702 "parser.y" /* yacc.c:1648  */
+#line 700 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr1(EXPR_NOT, (yyvsp[0].expr)); }
-#line 3971 "parser.tab.c" /* yacc.c:1648  */
+#line 3966 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 229:
-#line 703 "parser.y" /* yacc.c:1648  */
+#line 701 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr1(EXPR_POS, (yyvsp[0].expr)); }
-#line 3977 "parser.tab.c" /* yacc.c:1648  */
+#line 3972 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 230:
-#line 704 "parser.y" /* yacc.c:1648  */
+#line 702 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr1(EXPR_NEG, (yyvsp[0].expr)); }
-#line 3983 "parser.tab.c" /* yacc.c:1648  */
+#line 3978 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 231:
-#line 705 "parser.y" /* yacc.c:1648  */
+#line 703 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr1(EXPR_ADDRESSOF, (yyvsp[0].expr)); }
-#line 3989 "parser.tab.c" /* yacc.c:1648  */
+#line 3984 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 232:
-#line 706 "parser.y" /* yacc.c:1648  */
+#line 704 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr1(EXPR_PPTR, (yyvsp[0].expr)); }
-#line 3995 "parser.tab.c" /* yacc.c:1648  */
+#line 3990 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 233:
-#line 707 "parser.y" /* yacc.c:1648  */
+#line 705 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr2(EXPR_MEMBER, make_expr1(EXPR_PPTR, (yyvsp[-2].expr)), make_exprs(EXPR_IDENTIFIER, (yyvsp[0].str))); }
-#line 4001 "parser.tab.c" /* yacc.c:1648  */
+#line 3996 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 234:
-#line 708 "parser.y" /* yacc.c:1648  */
+#line 706 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr2(EXPR_MEMBER, (yyvsp[-2].expr), make_exprs(EXPR_IDENTIFIER, (yyvsp[0].str))); }
-#line 4007 "parser.tab.c" /* yacc.c:1648  */
+#line 4002 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 235:
-#line 710 "parser.y" /* yacc.c:1648  */
+#line 708 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_exprt(EXPR_CAST, declare_var(NULL, (yyvsp[-3].declspec), (yyvsp[-2].declarator), 0), (yyvsp[0].expr)); free((yyvsp[-3].declspec)); free((yyvsp[-2].declarator)); }
-#line 4013 "parser.tab.c" /* yacc.c:1648  */
+#line 4008 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 236:
-#line 712 "parser.y" /* yacc.c:1648  */
+#line 710 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_exprt(EXPR_SIZEOF, declare_var(NULL, (yyvsp[-2].declspec), (yyvsp[-1].declarator), 0), NULL); free((yyvsp[-2].declspec)); free((yyvsp[-1].declarator)); }
-#line 4019 "parser.tab.c" /* yacc.c:1648  */
+#line 4014 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 237:
-#line 713 "parser.y" /* yacc.c:1648  */
+#line 711 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = make_expr2(EXPR_ARRAY, (yyvsp[-3].expr), (yyvsp[-1].expr)); }
-#line 4025 "parser.tab.c" /* yacc.c:1648  */
+#line 4020 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 238:
-#line 714 "parser.y" /* yacc.c:1648  */
+#line 712 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = (yyvsp[-1].expr); }
-#line 4031 "parser.tab.c" /* yacc.c:1648  */
+#line 4026 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 239:
-#line 717 "parser.y" /* yacc.c:1648  */
+#line 715 "parser.y" /* yacc.c:1646  */
     { (yyval.expr_list) = append_expr( NULL, (yyvsp[0].expr) ); }
-#line 4037 "parser.tab.c" /* yacc.c:1648  */
+#line 4032 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 240:
-#line 718 "parser.y" /* yacc.c:1648  */
+#line 716 "parser.y" /* yacc.c:1646  */
     { (yyval.expr_list) = append_expr( (yyvsp[-2].expr_list), (yyvsp[0].expr) ); }
-#line 4043 "parser.tab.c" /* yacc.c:1648  */
+#line 4038 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 241:
-#line 721 "parser.y" /* yacc.c:1648  */
+#line 719 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = (yyvsp[0].expr);
 						  if (!(yyval.expr)->is_const)
 						      error_loc("expression is not an integer constant\n");
 						}
-#line 4052 "parser.tab.c" /* yacc.c:1648  */
+#line 4047 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 242:
-#line 727 "parser.y" /* yacc.c:1648  */
+#line 725 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = (yyvsp[0].expr);
 						  if (!(yyval.expr)->is_const && (yyval.expr)->type != EXPR_STRLIT && (yyval.expr)->type != EXPR_WSTRLIT)
 						      error_loc("expression is not constant\n");
 						}
-#line 4061 "parser.tab.c" /* yacc.c:1648  */
+#line 4056 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 243:
-#line 733 "parser.y" /* yacc.c:1648  */
+#line 731 "parser.y" /* yacc.c:1646  */
     { (yyval.var_list) = NULL; }
-#line 4067 "parser.tab.c" /* yacc.c:1648  */
+#line 4062 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 244:
-#line 734 "parser.y" /* yacc.c:1648  */
+#line 732 "parser.y" /* yacc.c:1646  */
     { (yyval.var_list) = append_var_list((yyvsp[-1].var_list), (yyvsp[0].var_list)); }
-#line 4073 "parser.tab.c" /* yacc.c:1648  */
+#line 4068 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 245:
-#line 738 "parser.y" /* yacc.c:1648  */
+#line 736 "parser.y" /* yacc.c:1646  */
     { const char *first = LIST_ENTRY(list_head((yyvsp[-1].declarator_list)), declarator_t, entry)->var->name;
 						  check_field_attrs(first, (yyvsp[-3].attr_list));
 						  (yyval.var_list) = set_var_types((yyvsp[-3].attr_list), (yyvsp[-2].declspec), (yyvsp[-1].declarator_list));
 						}
-#line 4082 "parser.tab.c" /* yacc.c:1648  */
+#line 4077 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 246:
-#line 742 "parser.y" /* yacc.c:1648  */
+#line 740 "parser.y" /* yacc.c:1646  */
     { var_t *v = make_var(NULL);
-						  v->type = (yyvsp[-1].type); v->attrs = (yyvsp[-2].attr_list);
+						  v->declspec.type = (yyvsp[-1].type); v->attrs = (yyvsp[-2].attr_list);
 						  (yyval.var_list) = append_var(NULL, v);
 						}
-#line 4091 "parser.tab.c" /* yacc.c:1648  */
+#line 4086 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 247:
-#line 749 "parser.y" /* yacc.c:1648  */
+#line 747 "parser.y" /* yacc.c:1646  */
     { (yyval.var) = (yyvsp[-1].var); }
-#line 4097 "parser.tab.c" /* yacc.c:1648  */
+#line 4092 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 248:
-#line 750 "parser.y" /* yacc.c:1648  */
+#line 748 "parser.y" /* yacc.c:1646  */
     { (yyval.var) = make_var(NULL); (yyval.var)->attrs = (yyvsp[-1].attr_list); }
-#line 4103 "parser.tab.c" /* yacc.c:1648  */
+#line 4098 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 249:
-#line 753 "parser.y" /* yacc.c:1648  */
+#line 751 "parser.y" /* yacc.c:1646  */
     { (yyval.var_list) = NULL; }
-#line 4109 "parser.tab.c" /* yacc.c:1648  */
+#line 4104 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 250:
-#line 754 "parser.y" /* yacc.c:1648  */
+#line 752 "parser.y" /* yacc.c:1646  */
     { (yyval.var_list) = append_var( (yyvsp[-1].var_list), (yyvsp[0].var) ); }
-#line 4115 "parser.tab.c" /* yacc.c:1648  */
+#line 4110 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 251:
-#line 758 "parser.y" /* yacc.c:1648  */
+#line 756 "parser.y" /* yacc.c:1646  */
     { (yyval.var) = (yyvsp[-1].var); }
-#line 4121 "parser.tab.c" /* yacc.c:1648  */
+#line 4116 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 252:
-#line 759 "parser.y" /* yacc.c:1648  */
+#line 757 "parser.y" /* yacc.c:1646  */
     { (yyval.var) = NULL; }
-#line 4127 "parser.tab.c" /* yacc.c:1648  */
+#line 4122 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 253:
-#line 762 "parser.y" /* yacc.c:1648  */
+#line 760 "parser.y" /* yacc.c:1646  */
     { (yyval.var) = declare_var(check_field_attrs((yyvsp[0].declarator)->var->name, (yyvsp[-2].attr_list)),
 						                (yyvsp[-1].declspec), (yyvsp[0].declarator), FALSE);
 						  free((yyvsp[0].declarator));
 						}
-#line 4136 "parser.tab.c" /* yacc.c:1648  */
+#line 4131 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 254:
-#line 766 "parser.y" /* yacc.c:1648  */
+#line 764 "parser.y" /* yacc.c:1646  */
     { var_t *v = make_var(NULL);
-						  v->type = (yyvsp[0].type); v->attrs = (yyvsp[-1].attr_list);
+						  v->declspec.type = (yyvsp[0].type); v->attrs = (yyvsp[-1].attr_list);
 						  (yyval.var) = v;
 						}
-#line 4145 "parser.tab.c" /* yacc.c:1648  */
+#line 4140 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 255:
-#line 772 "parser.y" /* yacc.c:1648  */
+#line 770 "parser.y" /* yacc.c:1646  */
     { (yyval.var) = (yyvsp[0].var);
-						  if (type_get_type((yyval.var)->type) != TYPE_FUNCTION)
+						  if (type_get_type((yyval.var)->declspec.type) != TYPE_FUNCTION)
 						    error_loc("only methods may be declared inside the methods section of a dispinterface\n");
 						  check_function_attrs((yyval.var)->name, (yyval.var)->attrs);
 						}
-#line 4155 "parser.tab.c" /* yacc.c:1648  */
+#line 4150 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 256:
-#line 781 "parser.y" /* yacc.c:1648  */
+#line 779 "parser.y" /* yacc.c:1646  */
     { (yyval.var) = declare_var((yyvsp[-2].attr_list), (yyvsp[-1].declspec), (yyvsp[0].declarator), FALSE);
 						  free((yyvsp[0].declarator));
 						}
-#line 4163 "parser.tab.c" /* yacc.c:1648  */
+#line 4158 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 257:
-#line 784 "parser.y" /* yacc.c:1648  */
+#line 782 "parser.y" /* yacc.c:1646  */
     { (yyval.var) = declare_var(NULL, (yyvsp[-1].declspec), (yyvsp[0].declarator), FALSE);
 						  free((yyvsp[0].declarator));
 						}
-#line 4171 "parser.tab.c" /* yacc.c:1648  */
+#line 4166 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 258:
-#line 789 "parser.y" /* yacc.c:1648  */
+#line 787 "parser.y" /* yacc.c:1646  */
     { (yyval.var) = NULL; }
-#line 4177 "parser.tab.c" /* yacc.c:1648  */
+#line 4172 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 260:
-#line 793 "parser.y" /* yacc.c:1648  */
+#line 791 "parser.y" /* yacc.c:1646  */
     { (yyval.str) = NULL; }
-#line 4183 "parser.tab.c" /* yacc.c:1648  */
+#line 4178 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 261:
-#line 794 "parser.y" /* yacc.c:1648  */
+#line 792 "parser.y" /* yacc.c:1646  */
     { (yyval.str) = (yyvsp[0].str); }
-#line 4189 "parser.tab.c" /* yacc.c:1648  */
+#line 4184 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 262:
-#line 795 "parser.y" /* yacc.c:1648  */
+#line 793 "parser.y" /* yacc.c:1646  */
     { (yyval.str) = (yyvsp[0].str); }
-#line 4195 "parser.tab.c" /* yacc.c:1648  */
+#line 4190 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 263:
-#line 798 "parser.y" /* yacc.c:1648  */
+#line 796 "parser.y" /* yacc.c:1646  */
     { (yyval.var) = make_var((yyvsp[0].str)); }
-#line 4201 "parser.tab.c" /* yacc.c:1648  */
+#line 4196 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 264:
-#line 800 "parser.y" /* yacc.c:1648  */
+#line 798 "parser.y" /* yacc.c:1646  */
     { (yyval.var) = make_var((yyvsp[0].str)); }
-#line 4207 "parser.tab.c" /* yacc.c:1648  */
+#line 4202 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 265:
-#line 803 "parser.y" /* yacc.c:1648  */
+#line 801 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = find_type_or_error((yyvsp[0].str), 0); }
-#line 4213 "parser.tab.c" /* yacc.c:1648  */
+#line 4208 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 266:
-#line 804 "parser.y" /* yacc.c:1648  */
+#line 802 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = find_type_or_error((yyvsp[0].str), 0); }
-#line 4219 "parser.tab.c" /* yacc.c:1648  */
+#line 4214 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 268:
-#line 806 "parser.y" /* yacc.c:1648  */
+#line 804 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = type_new_int(type_basic_get_type((yyvsp[0].type)), -1); }
-#line 4225 "parser.tab.c" /* yacc.c:1648  */
+#line 4220 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 269:
-#line 807 "parser.y" /* yacc.c:1648  */
+#line 805 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = type_new_int(type_basic_get_type((yyvsp[0].type)), 1); }
-#line 4231 "parser.tab.c" /* yacc.c:1648  */
+#line 4226 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 270:
-#line 808 "parser.y" /* yacc.c:1648  */
+#line 806 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = type_new_int(TYPE_BASIC_INT, 1); }
-#line 4237 "parser.tab.c" /* yacc.c:1648  */
+#line 4232 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 271:
-#line 809 "parser.y" /* yacc.c:1648  */
+#line 807 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = find_type_or_error((yyvsp[0].str), 0); }
-#line 4243 "parser.tab.c" /* yacc.c:1648  */
+#line 4238 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 272:
-#line 810 "parser.y" /* yacc.c:1648  */
+#line 808 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = find_type_or_error((yyvsp[0].str), 0); }
-#line 4249 "parser.tab.c" /* yacc.c:1648  */
+#line 4244 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 273:
-#line 811 "parser.y" /* yacc.c:1648  */
+#line 809 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = find_type_or_error((yyvsp[0].str), 0); }
-#line 4255 "parser.tab.c" /* yacc.c:1648  */
+#line 4250 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 274:
-#line 812 "parser.y" /* yacc.c:1648  */
+#line 810 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = find_type_or_error((yyvsp[0].str), 0); }
-#line 4261 "parser.tab.c" /* yacc.c:1648  */
+#line 4256 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 275:
-#line 813 "parser.y" /* yacc.c:1648  */
+#line 811 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = find_type_or_error((yyvsp[0].str), 0); }
-#line 4267 "parser.tab.c" /* yacc.c:1648  */
+#line 4262 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 278:
-#line 820 "parser.y" /* yacc.c:1648  */
+#line 818 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = type_new_int(TYPE_BASIC_INT, 0); }
-#line 4273 "parser.tab.c" /* yacc.c:1648  */
+#line 4268 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 279:
-#line 821 "parser.y" /* yacc.c:1648  */
+#line 819 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = type_new_int(TYPE_BASIC_INT16, 0); }
-#line 4279 "parser.tab.c" /* yacc.c:1648  */
+#line 4274 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 280:
-#line 822 "parser.y" /* yacc.c:1648  */
+#line 820 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = type_new_int(TYPE_BASIC_INT8, 0); }
-#line 4285 "parser.tab.c" /* yacc.c:1648  */
+#line 4280 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 281:
-#line 823 "parser.y" /* yacc.c:1648  */
+#line 821 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = type_new_int(TYPE_BASIC_LONG, 0); }
-#line 4291 "parser.tab.c" /* yacc.c:1648  */
+#line 4286 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 282:
-#line 824 "parser.y" /* yacc.c:1648  */
+#line 822 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = type_new_int(TYPE_BASIC_HYPER, 0); }
-#line 4297 "parser.tab.c" /* yacc.c:1648  */
+#line 4292 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 283:
-#line 825 "parser.y" /* yacc.c:1648  */
+#line 823 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = type_new_int(TYPE_BASIC_INT64, 0); }
-#line 4303 "parser.tab.c" /* yacc.c:1648  */
+#line 4298 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 284:
-#line 826 "parser.y" /* yacc.c:1648  */
+#line 824 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = type_new_int(TYPE_BASIC_CHAR, 0); }
-#line 4309 "parser.tab.c" /* yacc.c:1648  */
+#line 4304 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 285:
-#line 827 "parser.y" /* yacc.c:1648  */
+#line 825 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = type_new_int(TYPE_BASIC_INT32, 0); }
-#line 4315 "parser.tab.c" /* yacc.c:1648  */
+#line 4310 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 286:
-#line 828 "parser.y" /* yacc.c:1648  */
+#line 826 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = type_new_int(TYPE_BASIC_INT3264, 0); }
-#line 4321 "parser.tab.c" /* yacc.c:1648  */
+#line 4316 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 287:
-#line 831 "parser.y" /* yacc.c:1648  */
+#line 829 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = type_new_coclass((yyvsp[0].str)); }
-#line 4327 "parser.tab.c" /* yacc.c:1648  */
+#line 4322 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 288:
-#line 832 "parser.y" /* yacc.c:1648  */
+#line 830 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = find_type((yyvsp[0].str), NULL, 0);
 						  if (type_get_type_detect_alias((yyval.type)) != TYPE_COCLASS)
 						    error_loc("%s was not declared a coclass at %s:%d\n",
 							      (yyvsp[0].str), (yyval.type)->loc_info.input_name,
 							      (yyval.type)->loc_info.line_number);
 						}
-#line 4338 "parser.tab.c" /* yacc.c:1648  */
+#line 4333 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 289:
-#line 840 "parser.y" /* yacc.c:1648  */
+#line 838 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = (yyvsp[0].type);
 						  check_def((yyval.type));
 						  (yyval.type)->attrs = check_coclass_attrs((yyvsp[0].type)->name, (yyvsp[-1].attr_list));
 						}
-#line 4347 "parser.tab.c" /* yacc.c:1648  */
+#line 4342 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 290:
-#line 847 "parser.y" /* yacc.c:1648  */
+#line 845 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = type_coclass_define((yyvsp[-4].type), (yyvsp[-2].ifref_list)); }
-#line 4353 "parser.tab.c" /* yacc.c:1648  */
+#line 4348 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 291:
-#line 850 "parser.y" /* yacc.c:1648  */
+#line 848 "parser.y" /* yacc.c:1646  */
     { (yyval.str) = (yyvsp[0].str); }
-#line 4359 "parser.tab.c" /* yacc.c:1648  */
+#line 4354 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 292:
-#line 853 "parser.y" /* yacc.c:1648  */
+#line 851 "parser.y" /* yacc.c:1646  */
     { (yyval.ifref_list) = NULL; }
-#line 4365 "parser.tab.c" /* yacc.c:1648  */
+#line 4360 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 293:
-#line 854 "parser.y" /* yacc.c:1648  */
+#line 852 "parser.y" /* yacc.c:1646  */
     { (yyval.ifref_list) = append_ifref( (yyvsp[-1].ifref_list), (yyvsp[0].ifref) ); }
-#line 4371 "parser.tab.c" /* yacc.c:1648  */
+#line 4366 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 294:
-#line 858 "parser.y" /* yacc.c:1648  */
+#line 856 "parser.y" /* yacc.c:1646  */
     { (yyval.ifref) = make_ifref((yyvsp[0].type)); (yyval.ifref)->attrs = (yyvsp[-1].attr_list); }
-#line 4377 "parser.tab.c" /* yacc.c:1648  */
+#line 4372 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 295:
-#line 861 "parser.y" /* yacc.c:1648  */
+#line 859 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = get_type(TYPE_INTERFACE, (yyvsp[0].str), current_namespace, 0); }
-#line 4383 "parser.tab.c" /* yacc.c:1648  */
+#line 4378 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 296:
-#line 862 "parser.y" /* yacc.c:1648  */
+#line 860 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = get_type(TYPE_INTERFACE, (yyvsp[0].str), current_namespace, 0); }
-#line 4389 "parser.tab.c" /* yacc.c:1648  */
+#line 4384 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 297:
-#line 865 "parser.y" /* yacc.c:1648  */
+#line 863 "parser.y" /* yacc.c:1646  */
     { attr_t *attrs;
 						  (yyval.type) = (yyvsp[0].type);
 						  check_def((yyval.type));
@@ -4397,75 +4392,75 @@ yyreduce:
 						  (yyval.type)->attrs = append_attr( check_dispiface_attrs((yyvsp[0].type)->name, (yyvsp[-1].attr_list)), attrs );
 						  (yyval.type)->defined = TRUE;
 						}
-#line 4401 "parser.tab.c" /* yacc.c:1648  */
+#line 4396 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 298:
-#line 874 "parser.y" /* yacc.c:1648  */
+#line 872 "parser.y" /* yacc.c:1646  */
     { (yyval.var_list) = NULL; }
-#line 4407 "parser.tab.c" /* yacc.c:1648  */
+#line 4402 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 299:
-#line 875 "parser.y" /* yacc.c:1648  */
+#line 873 "parser.y" /* yacc.c:1646  */
     { (yyval.var_list) = append_var( (yyvsp[-2].var_list), (yyvsp[-1].var) ); }
-#line 4413 "parser.tab.c" /* yacc.c:1648  */
+#line 4408 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 300:
-#line 878 "parser.y" /* yacc.c:1648  */
+#line 876 "parser.y" /* yacc.c:1646  */
     { (yyval.var_list) = NULL; }
-#line 4419 "parser.tab.c" /* yacc.c:1648  */
+#line 4414 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 301:
-#line 879 "parser.y" /* yacc.c:1648  */
+#line 877 "parser.y" /* yacc.c:1646  */
     { (yyval.var_list) = append_var( (yyvsp[-2].var_list), (yyvsp[-1].var) ); }
-#line 4425 "parser.tab.c" /* yacc.c:1648  */
+#line 4420 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 302:
-#line 885 "parser.y" /* yacc.c:1648  */
+#line 883 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = (yyvsp[-4].type);
 						  type_dispinterface_define((yyval.type), (yyvsp[-2].var_list), (yyvsp[-1].var_list));
 						}
-#line 4433 "parser.tab.c" /* yacc.c:1648  */
+#line 4428 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 303:
-#line 889 "parser.y" /* yacc.c:1648  */
+#line 887 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = (yyvsp[-4].type);
 						  type_dispinterface_define_from_iface((yyval.type), (yyvsp[-2].type));
 						}
-#line 4441 "parser.tab.c" /* yacc.c:1648  */
+#line 4436 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 304:
-#line 894 "parser.y" /* yacc.c:1648  */
+#line 892 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = NULL; }
-#line 4447 "parser.tab.c" /* yacc.c:1648  */
+#line 4442 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 305:
-#line 895 "parser.y" /* yacc.c:1648  */
+#line 893 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = find_type_or_error2((yyvsp[0].str), 0); }
-#line 4453 "parser.tab.c" /* yacc.c:1648  */
+#line 4448 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 306:
-#line 898 "parser.y" /* yacc.c:1648  */
+#line 896 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = get_type(TYPE_INTERFACE, (yyvsp[0].str), current_namespace, 0); }
-#line 4459 "parser.tab.c" /* yacc.c:1648  */
+#line 4454 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 307:
-#line 899 "parser.y" /* yacc.c:1648  */
+#line 897 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = get_type(TYPE_INTERFACE, (yyvsp[0].str), current_namespace, 0); }
-#line 4465 "parser.tab.c" /* yacc.c:1648  */
+#line 4460 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 308:
-#line 902 "parser.y" /* yacc.c:1648  */
+#line 900 "parser.y" /* yacc.c:1646  */
     { (yyval.ifinfo).interface = (yyvsp[0].type);
 						  (yyval.ifinfo).old_pointer_default = pointer_default;
 						  if (is_attr((yyvsp[-1].attr_list), ATTR_POINTERDEFAULT))
@@ -4474,11 +4469,11 @@ yyreduce:
 						  (yyvsp[0].type)->attrs = check_iface_attrs((yyvsp[0].type)->name, (yyvsp[-1].attr_list));
 						  (yyvsp[0].type)->defined = TRUE;
 						}
-#line 4478 "parser.tab.c" /* yacc.c:1648  */
+#line 4473 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 309:
-#line 913 "parser.y" /* yacc.c:1648  */
+#line 911 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = (yyvsp[-5].ifinfo).interface;
 						  if((yyval.type) == (yyvsp[-4].type))
 						    error_loc("Interface can't inherit from itself\n");
@@ -4486,594 +4481,594 @@ yyreduce:
 						  check_async_uuid((yyval.type));
 						  pointer_default = (yyvsp[-5].ifinfo).old_pointer_default;
 						}
-#line 4490 "parser.tab.c" /* yacc.c:1648  */
+#line 4485 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 310:
-#line 924 "parser.y" /* yacc.c:1648  */
+#line 922 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = (yyvsp[-7].ifinfo).interface;
 						  type_interface_define((yyval.type), find_type_or_error2((yyvsp[-5].str), 0), (yyvsp[-2].stmt_list));
 						  pointer_default = (yyvsp[-7].ifinfo).old_pointer_default;
 						}
-#line 4499 "parser.tab.c" /* yacc.c:1648  */
+#line 4494 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 311:
-#line 928 "parser.y" /* yacc.c:1648  */
+#line 926 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = (yyvsp[-1].type); }
-#line 4505 "parser.tab.c" /* yacc.c:1648  */
+#line 4500 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 312:
-#line 932 "parser.y" /* yacc.c:1648  */
+#line 930 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = (yyvsp[-1].type); }
-#line 4511 "parser.tab.c" /* yacc.c:1648  */
+#line 4506 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 313:
-#line 933 "parser.y" /* yacc.c:1648  */
+#line 931 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = (yyvsp[-1].type); }
-#line 4517 "parser.tab.c" /* yacc.c:1648  */
+#line 4512 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 314:
-#line 936 "parser.y" /* yacc.c:1648  */
+#line 934 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = type_new_module((yyvsp[0].str)); }
-#line 4523 "parser.tab.c" /* yacc.c:1648  */
+#line 4518 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 315:
-#line 937 "parser.y" /* yacc.c:1648  */
+#line 935 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = type_new_module((yyvsp[0].str)); }
-#line 4529 "parser.tab.c" /* yacc.c:1648  */
+#line 4524 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 316:
-#line 940 "parser.y" /* yacc.c:1648  */
+#line 938 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = (yyvsp[0].type);
 						  (yyval.type)->attrs = check_module_attrs((yyvsp[0].type)->name, (yyvsp[-1].attr_list));
 						}
-#line 4537 "parser.tab.c" /* yacc.c:1648  */
+#line 4532 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 317:
-#line 946 "parser.y" /* yacc.c:1648  */
+#line 944 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = (yyvsp[-4].type);
                                                   type_module_define((yyval.type), (yyvsp[-2].stmt_list));
 						}
-#line 4545 "parser.tab.c" /* yacc.c:1648  */
+#line 4540 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 318:
-#line 952 "parser.y" /* yacc.c:1648  */
+#line 950 "parser.y" /* yacc.c:1646  */
     { (yyval.stgclass) = STG_EXTERN; }
-#line 4551 "parser.tab.c" /* yacc.c:1648  */
+#line 4546 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 319:
-#line 953 "parser.y" /* yacc.c:1648  */
+#line 951 "parser.y" /* yacc.c:1646  */
     { (yyval.stgclass) = STG_STATIC; }
-#line 4557 "parser.tab.c" /* yacc.c:1648  */
+#line 4552 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 320:
-#line 954 "parser.y" /* yacc.c:1648  */
+#line 952 "parser.y" /* yacc.c:1646  */
     { (yyval.stgclass) = STG_REGISTER; }
-#line 4563 "parser.tab.c" /* yacc.c:1648  */
+#line 4558 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 321:
-#line 958 "parser.y" /* yacc.c:1648  */
-    { (yyval.attr) = make_attr(ATTR_INLINE); }
-#line 4569 "parser.tab.c" /* yacc.c:1648  */
+#line 956 "parser.y" /* yacc.c:1646  */
+    { (yyval.funcspecifier) = FUNCTION_SPECIFIER_INLINE; }
+#line 4564 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 322:
-#line 962 "parser.y" /* yacc.c:1648  */
-    { (yyval.attr) = make_attr(ATTR_CONST); }
-#line 4575 "parser.tab.c" /* yacc.c:1648  */
+#line 960 "parser.y" /* yacc.c:1646  */
+    { (yyval.typequalifier) = TYPE_QUALIFIER_CONST; }
+#line 4570 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 323:
-#line 965 "parser.y" /* yacc.c:1648  */
-    { (yyval.attr_list) = NULL; }
-#line 4581 "parser.tab.c" /* yacc.c:1648  */
+#line 963 "parser.y" /* yacc.c:1646  */
+    { (yyval.typequalifier) = TYPE_QUALIFIER_NONE; }
+#line 4576 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 324:
-#line 966 "parser.y" /* yacc.c:1648  */
-    { (yyval.attr_list) = append_attr((yyvsp[-1].attr_list), (yyvsp[0].attr)); }
-#line 4587 "parser.tab.c" /* yacc.c:1648  */
+#line 964 "parser.y" /* yacc.c:1646  */
+    { (yyval.typequalifier) = (yyvsp[-1].typequalifier) | (yyvsp[0].typequalifier); }
+#line 4582 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 325:
-#line 969 "parser.y" /* yacc.c:1648  */
-    { (yyval.declspec) = make_decl_spec((yyvsp[-1].type), (yyvsp[0].declspec), NULL, NULL, STG_NONE); }
-#line 4593 "parser.tab.c" /* yacc.c:1648  */
+#line 967 "parser.y" /* yacc.c:1646  */
+    { (yyval.declspec) = make_decl_spec((yyvsp[-1].type), (yyvsp[0].declspec), NULL, STG_NONE, TYPE_QUALIFIER_NONE, FUNCTION_SPECIFIER_NONE); }
+#line 4588 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 326:
-#line 971 "parser.y" /* yacc.c:1648  */
-    { (yyval.declspec) = make_decl_spec((yyvsp[-1].type), (yyvsp[-2].declspec), (yyvsp[0].declspec), NULL, STG_NONE); }
-#line 4599 "parser.tab.c" /* yacc.c:1648  */
+#line 969 "parser.y" /* yacc.c:1646  */
+    { (yyval.declspec) = make_decl_spec((yyvsp[-1].type), (yyvsp[-2].declspec), (yyvsp[0].declspec), STG_NONE, TYPE_QUALIFIER_NONE, FUNCTION_SPECIFIER_NONE); }
+#line 4594 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 327:
-#line 974 "parser.y" /* yacc.c:1648  */
+#line 972 "parser.y" /* yacc.c:1646  */
     { (yyval.declspec) = NULL; }
-#line 4605 "parser.tab.c" /* yacc.c:1648  */
+#line 4600 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 329:
-#line 979 "parser.y" /* yacc.c:1648  */
-    { (yyval.declspec) = make_decl_spec(NULL, (yyvsp[0].declspec), NULL, (yyvsp[-1].attr), STG_NONE); }
-#line 4611 "parser.tab.c" /* yacc.c:1648  */
+#line 977 "parser.y" /* yacc.c:1646  */
+    { (yyval.declspec) = make_decl_spec(NULL, (yyvsp[0].declspec), NULL, STG_NONE, (yyvsp[-1].typequalifier), FUNCTION_SPECIFIER_NONE); }
+#line 4606 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 330:
-#line 980 "parser.y" /* yacc.c:1648  */
-    { (yyval.declspec) = make_decl_spec(NULL, (yyvsp[0].declspec), NULL, (yyvsp[-1].attr), STG_NONE); }
-#line 4617 "parser.tab.c" /* yacc.c:1648  */
+#line 978 "parser.y" /* yacc.c:1646  */
+    { (yyval.declspec) = make_decl_spec(NULL, (yyvsp[0].declspec), NULL, STG_NONE, TYPE_QUALIFIER_NONE, (yyvsp[-1].funcspecifier)); }
+#line 4612 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 331:
-#line 981 "parser.y" /* yacc.c:1648  */
-    { (yyval.declspec) = make_decl_spec(NULL, (yyvsp[0].declspec), NULL, NULL, (yyvsp[-1].stgclass)); }
-#line 4623 "parser.tab.c" /* yacc.c:1648  */
+#line 979 "parser.y" /* yacc.c:1646  */
+    { (yyval.declspec) = make_decl_spec(NULL, (yyvsp[0].declspec), NULL, (yyvsp[-1].stgclass), TYPE_QUALIFIER_NONE, FUNCTION_SPECIFIER_NONE); }
+#line 4618 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 332:
-#line 986 "parser.y" /* yacc.c:1648  */
-    { (yyval.declarator) = (yyvsp[0].declarator); (yyval.declarator)->type = append_chain_type((yyval.declarator)->type, type_new_pointer(pointer_default, NULL, (yyvsp[-1].attr_list))); }
-#line 4629 "parser.tab.c" /* yacc.c:1648  */
+#line 984 "parser.y" /* yacc.c:1646  */
+    { (yyval.declarator) = (yyvsp[0].declarator); append_chain_declspec(&(yyval.declarator)->declspec, type_new_pointer(pointer_default, NULL), (yyvsp[-1].typequalifier)); }
+#line 4624 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 333:
-#line 987 "parser.y" /* yacc.c:1648  */
+#line 985 "parser.y" /* yacc.c:1646  */
     { (yyval.declarator) = (yyvsp[0].declarator); if ((yyval.declarator)->func_type) (yyval.declarator)->func_type->attrs = append_attr((yyval.declarator)->func_type->attrs, make_attrp(ATTR_CALLCONV, (yyvsp[-1].str)));
-						           else if ((yyval.declarator)->type) (yyval.declarator)->type->attrs = append_attr((yyval.declarator)->type->attrs, make_attrp(ATTR_CALLCONV, (yyvsp[-1].str))); }
-#line 4636 "parser.tab.c" /* yacc.c:1648  */
+						           else if ((yyval.declarator)->declspec.type) (yyval.declarator)->declspec.type->attrs = append_attr((yyval.declarator)->declspec.type->attrs, make_attrp(ATTR_CALLCONV, (yyvsp[-1].str))); }
+#line 4631 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 335:
-#line 993 "parser.y" /* yacc.c:1648  */
+#line 991 "parser.y" /* yacc.c:1646  */
     { (yyval.declarator) = make_declarator((yyvsp[0].var)); }
-#line 4642 "parser.tab.c" /* yacc.c:1648  */
+#line 4637 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 336:
-#line 994 "parser.y" /* yacc.c:1648  */
+#line 992 "parser.y" /* yacc.c:1646  */
     { (yyval.declarator) = (yyvsp[-1].declarator); }
-#line 4648 "parser.tab.c" /* yacc.c:1648  */
+#line 4643 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 337:
-#line 995 "parser.y" /* yacc.c:1648  */
-    { (yyval.declarator) = (yyvsp[-1].declarator); (yyval.declarator)->type = append_array((yyval.declarator)->type, (yyvsp[0].expr)); }
-#line 4654 "parser.tab.c" /* yacc.c:1648  */
+#line 993 "parser.y" /* yacc.c:1646  */
+    { (yyval.declarator) = (yyvsp[-1].declarator); (yyval.declarator)->declspec.type = append_array((yyval.declarator)->declspec.type, (yyvsp[0].expr)); }
+#line 4649 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 338:
-#line 996 "parser.y" /* yacc.c:1648  */
+#line 994 "parser.y" /* yacc.c:1646  */
     { (yyval.declarator) = (yyvsp[-3].declarator);
-						  (yyval.declarator)->func_type = append_chain_type((yyval.declarator)->type, type_new_function((yyvsp[-1].var_list)));
-						  (yyval.declarator)->type = NULL;
+						  (yyval.declarator)->func_type = append_chain_type((yyval.declarator)->declspec.type, type_new_function((yyvsp[-1].var_list)));
+						  (yyval.declarator)->declspec.type = NULL;
 						}
-#line 4663 "parser.tab.c" /* yacc.c:1648  */
+#line 4658 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 339:
-#line 1005 "parser.y" /* yacc.c:1648  */
-    { (yyval.declarator) = (yyvsp[0].declarator); (yyval.declarator)->type = append_chain_type((yyval.declarator)->type, type_new_pointer(pointer_default, NULL, (yyvsp[-1].attr_list))); }
-#line 4669 "parser.tab.c" /* yacc.c:1648  */
+#line 1003 "parser.y" /* yacc.c:1646  */
+    { (yyval.declarator) = (yyvsp[0].declarator); append_chain_declspec(&(yyval.declarator)->declspec, type_new_pointer(pointer_default, NULL), (yyvsp[-1].typequalifier)); }
+#line 4664 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 340:
-#line 1006 "parser.y" /* yacc.c:1648  */
+#line 1004 "parser.y" /* yacc.c:1646  */
     { (yyval.declarator) = (yyvsp[0].declarator); if ((yyval.declarator)->func_type) (yyval.declarator)->func_type->attrs = append_attr((yyval.declarator)->func_type->attrs, make_attrp(ATTR_CALLCONV, (yyvsp[-1].str)));
-						           else if ((yyval.declarator)->type) (yyval.declarator)->type->attrs = append_attr((yyval.declarator)->type->attrs, make_attrp(ATTR_CALLCONV, (yyvsp[-1].str))); }
-#line 4676 "parser.tab.c" /* yacc.c:1648  */
+						           else if ((yyval.declarator)->declspec.type) (yyval.declarator)->declspec.type->attrs = append_attr((yyval.declarator)->declspec.type->attrs, make_attrp(ATTR_CALLCONV, (yyvsp[-1].str))); }
+#line 4671 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 342:
-#line 1014 "parser.y" /* yacc.c:1648  */
-    { (yyval.declarator) = (yyvsp[0].declarator); (yyval.declarator)->type = append_chain_type((yyval.declarator)->type, type_new_pointer(pointer_default, NULL, (yyvsp[-1].attr_list))); }
-#line 4682 "parser.tab.c" /* yacc.c:1648  */
+#line 1012 "parser.y" /* yacc.c:1646  */
+    { (yyval.declarator) = (yyvsp[0].declarator); append_chain_declspec(&(yyval.declarator)->declspec, type_new_pointer(pointer_default, NULL), (yyvsp[-1].typequalifier)); }
+#line 4677 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 343:
-#line 1015 "parser.y" /* yacc.c:1648  */
+#line 1013 "parser.y" /* yacc.c:1646  */
     { (yyval.declarator) = (yyvsp[0].declarator); if ((yyval.declarator)->func_type) (yyval.declarator)->func_type->attrs = append_attr((yyval.declarator)->func_type->attrs, make_attrp(ATTR_CALLCONV, (yyvsp[-1].str)));
-						           else if ((yyval.declarator)->type) (yyval.declarator)->type->attrs = append_attr((yyval.declarator)->type->attrs, make_attrp(ATTR_CALLCONV, (yyvsp[-1].str))); }
-#line 4689 "parser.tab.c" /* yacc.c:1648  */
+						           else if ((yyval.declarator)->declspec.type) (yyval.declarator)->declspec.type->attrs = append_attr((yyval.declarator)->declspec.type->attrs, make_attrp(ATTR_CALLCONV, (yyvsp[-1].str))); }
+#line 4684 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 344:
-#line 1020 "parser.y" /* yacc.c:1648  */
+#line 1018 "parser.y" /* yacc.c:1646  */
     { (yyval.declarator) = make_declarator(NULL); }
-#line 4695 "parser.tab.c" /* yacc.c:1648  */
+#line 4690 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 346:
-#line 1026 "parser.y" /* yacc.c:1648  */
+#line 1024 "parser.y" /* yacc.c:1646  */
     { (yyval.declarator) = (yyvsp[-1].declarator); }
-#line 4701 "parser.tab.c" /* yacc.c:1648  */
+#line 4696 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 347:
-#line 1027 "parser.y" /* yacc.c:1648  */
-    { (yyval.declarator) = (yyvsp[-1].declarator); (yyval.declarator)->type = append_array((yyval.declarator)->type, (yyvsp[0].expr)); }
-#line 4707 "parser.tab.c" /* yacc.c:1648  */
+#line 1025 "parser.y" /* yacc.c:1646  */
+    { (yyval.declarator) = (yyvsp[-1].declarator); (yyval.declarator)->declspec.type = append_array((yyval.declarator)->declspec.type, (yyvsp[0].expr)); }
+#line 4702 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 348:
-#line 1028 "parser.y" /* yacc.c:1648  */
-    { (yyval.declarator) = make_declarator(NULL); (yyval.declarator)->type = append_array((yyval.declarator)->type, (yyvsp[0].expr)); }
-#line 4713 "parser.tab.c" /* yacc.c:1648  */
+#line 1026 "parser.y" /* yacc.c:1646  */
+    { (yyval.declarator) = make_declarator(NULL); (yyval.declarator)->declspec.type = append_array((yyval.declarator)->declspec.type, (yyvsp[0].expr)); }
+#line 4708 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 349:
-#line 1030 "parser.y" /* yacc.c:1648  */
+#line 1028 "parser.y" /* yacc.c:1646  */
     { (yyval.declarator) = make_declarator(NULL);
-						  (yyval.declarator)->func_type = append_chain_type((yyval.declarator)->type, type_new_function((yyvsp[-1].var_list)));
-						  (yyval.declarator)->type = NULL;
+						  (yyval.declarator)->func_type = append_chain_type((yyval.declarator)->declspec.type, type_new_function((yyvsp[-1].var_list)));
+						  (yyval.declarator)->declspec.type = NULL;
 						}
-#line 4722 "parser.tab.c" /* yacc.c:1648  */
+#line 4717 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 350:
-#line 1035 "parser.y" /* yacc.c:1648  */
+#line 1033 "parser.y" /* yacc.c:1646  */
     { (yyval.declarator) = (yyvsp[-3].declarator);
-						  (yyval.declarator)->func_type = append_chain_type((yyval.declarator)->type, type_new_function((yyvsp[-1].var_list)));
-						  (yyval.declarator)->type = NULL;
+						  (yyval.declarator)->func_type = append_chain_type((yyval.declarator)->declspec.type, type_new_function((yyvsp[-1].var_list)));
+						  (yyval.declarator)->declspec.type = NULL;
 						}
-#line 4731 "parser.tab.c" /* yacc.c:1648  */
+#line 4726 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 351:
-#line 1044 "parser.y" /* yacc.c:1648  */
-    { (yyval.declarator) = (yyvsp[0].declarator); (yyval.declarator)->type = append_chain_type((yyval.declarator)->type, type_new_pointer(pointer_default, NULL, (yyvsp[-1].attr_list))); }
-#line 4737 "parser.tab.c" /* yacc.c:1648  */
+#line 1042 "parser.y" /* yacc.c:1646  */
+    { (yyval.declarator) = (yyvsp[0].declarator); append_chain_declspec(&(yyval.declarator)->declspec, type_new_pointer(pointer_default, NULL), (yyvsp[-1].typequalifier)); }
+#line 4732 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 352:
-#line 1045 "parser.y" /* yacc.c:1648  */
-    { (yyval.declarator) = (yyvsp[0].declarator); (yyval.declarator)->type->attrs = append_attr((yyval.declarator)->type->attrs, make_attrp(ATTR_CALLCONV, (yyvsp[-1].str))); }
-#line 4743 "parser.tab.c" /* yacc.c:1648  */
+#line 1043 "parser.y" /* yacc.c:1646  */
+    { (yyval.declarator) = (yyvsp[0].declarator); (yyval.declarator)->declspec.type->attrs = append_attr((yyval.declarator)->declspec.type->attrs, make_attrp(ATTR_CALLCONV, (yyvsp[-1].str))); }
+#line 4738 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 354:
-#line 1052 "parser.y" /* yacc.c:1648  */
-    { (yyval.declarator) = (yyvsp[0].declarator); (yyval.declarator)->type = append_chain_type((yyval.declarator)->type, type_new_pointer(pointer_default, NULL, (yyvsp[-1].attr_list))); }
-#line 4749 "parser.tab.c" /* yacc.c:1648  */
+#line 1050 "parser.y" /* yacc.c:1646  */
+    { (yyval.declarator) = (yyvsp[0].declarator); append_chain_declspec(&(yyval.declarator)->declspec, type_new_pointer(pointer_default, NULL), (yyvsp[-1].typequalifier)); }
+#line 4744 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 355:
-#line 1053 "parser.y" /* yacc.c:1648  */
-    { (yyval.declarator) = (yyvsp[0].declarator); (yyval.declarator)->type->attrs = append_attr((yyval.declarator)->type->attrs, make_attrp(ATTR_CALLCONV, (yyvsp[-1].str))); }
-#line 4755 "parser.tab.c" /* yacc.c:1648  */
+#line 1051 "parser.y" /* yacc.c:1646  */
+    { (yyval.declarator) = (yyvsp[0].declarator); (yyval.declarator)->declspec.type->attrs = append_attr((yyval.declarator)->declspec.type->attrs, make_attrp(ATTR_CALLCONV, (yyvsp[-1].str))); }
+#line 4750 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 356:
-#line 1057 "parser.y" /* yacc.c:1648  */
+#line 1055 "parser.y" /* yacc.c:1646  */
     { (yyval.declarator) = make_declarator(NULL); }
-#line 4761 "parser.tab.c" /* yacc.c:1648  */
+#line 4756 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 358:
-#line 1065 "parser.y" /* yacc.c:1648  */
+#line 1063 "parser.y" /* yacc.c:1646  */
     { (yyval.declarator) = make_declarator((yyvsp[0].var)); }
-#line 4767 "parser.tab.c" /* yacc.c:1648  */
+#line 4762 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 359:
-#line 1066 "parser.y" /* yacc.c:1648  */
+#line 1064 "parser.y" /* yacc.c:1646  */
     { (yyval.declarator) = (yyvsp[-1].declarator); }
-#line 4773 "parser.tab.c" /* yacc.c:1648  */
+#line 4768 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 360:
-#line 1067 "parser.y" /* yacc.c:1648  */
-    { (yyval.declarator) = (yyvsp[-1].declarator); (yyval.declarator)->type = append_array((yyval.declarator)->type, (yyvsp[0].expr)); }
-#line 4779 "parser.tab.c" /* yacc.c:1648  */
+#line 1065 "parser.y" /* yacc.c:1646  */
+    { (yyval.declarator) = (yyvsp[-1].declarator); (yyval.declarator)->declspec.type = append_array((yyval.declarator)->declspec.type, (yyvsp[0].expr)); }
+#line 4774 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 361:
-#line 1068 "parser.y" /* yacc.c:1648  */
-    { (yyval.declarator) = make_declarator(NULL); (yyval.declarator)->type = append_array((yyval.declarator)->type, (yyvsp[0].expr)); }
-#line 4785 "parser.tab.c" /* yacc.c:1648  */
+#line 1066 "parser.y" /* yacc.c:1646  */
+    { (yyval.declarator) = make_declarator(NULL); (yyval.declarator)->declspec.type = append_array((yyval.declarator)->declspec.type, (yyvsp[0].expr)); }
+#line 4780 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 362:
-#line 1070 "parser.y" /* yacc.c:1648  */
+#line 1068 "parser.y" /* yacc.c:1646  */
     { (yyval.declarator) = make_declarator(NULL);
-						  (yyval.declarator)->func_type = append_chain_type((yyval.declarator)->type, type_new_function((yyvsp[-1].var_list)));
-						  (yyval.declarator)->type = NULL;
+						  (yyval.declarator)->func_type = append_chain_type((yyval.declarator)->declspec.type, type_new_function((yyvsp[-1].var_list)));
+						  (yyval.declarator)->declspec.type = NULL;
 						}
-#line 4794 "parser.tab.c" /* yacc.c:1648  */
+#line 4789 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 363:
-#line 1075 "parser.y" /* yacc.c:1648  */
+#line 1073 "parser.y" /* yacc.c:1646  */
     { (yyval.declarator) = (yyvsp[-3].declarator);
-						  (yyval.declarator)->func_type = append_chain_type((yyval.declarator)->type, type_new_function((yyvsp[-1].var_list)));
-						  (yyval.declarator)->type = NULL;
+						  (yyval.declarator)->func_type = append_chain_type((yyval.declarator)->declspec.type, type_new_function((yyvsp[-1].var_list)));
+						  (yyval.declarator)->declspec.type = NULL;
 						}
-#line 4803 "parser.tab.c" /* yacc.c:1648  */
+#line 4798 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 364:
-#line 1082 "parser.y" /* yacc.c:1648  */
+#line 1080 "parser.y" /* yacc.c:1646  */
     { (yyval.declarator_list) = append_declarator( NULL, (yyvsp[0].declarator) ); }
-#line 4809 "parser.tab.c" /* yacc.c:1648  */
+#line 4804 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 365:
-#line 1083 "parser.y" /* yacc.c:1648  */
+#line 1081 "parser.y" /* yacc.c:1646  */
     { (yyval.declarator_list) = append_declarator( (yyvsp[-2].declarator_list), (yyvsp[0].declarator) ); }
-#line 4815 "parser.tab.c" /* yacc.c:1648  */
+#line 4810 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 366:
-#line 1086 "parser.y" /* yacc.c:1648  */
+#line 1084 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = NULL; }
-#line 4821 "parser.tab.c" /* yacc.c:1648  */
+#line 4816 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 367:
-#line 1087 "parser.y" /* yacc.c:1648  */
+#line 1085 "parser.y" /* yacc.c:1646  */
     { (yyval.expr) = (yyvsp[0].expr); }
-#line 4827 "parser.tab.c" /* yacc.c:1648  */
+#line 4822 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 368:
-#line 1090 "parser.y" /* yacc.c:1648  */
+#line 1088 "parser.y" /* yacc.c:1646  */
     { (yyval.declarator) = (yyvsp[-1].declarator); (yyval.declarator)->bits = (yyvsp[0].expr);
 						  if (!(yyval.declarator)->bits && !(yyval.declarator)->var->name)
 						    error_loc("unnamed fields are not allowed\n");
 						}
-#line 4836 "parser.tab.c" /* yacc.c:1648  */
+#line 4831 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 369:
-#line 1097 "parser.y" /* yacc.c:1648  */
+#line 1095 "parser.y" /* yacc.c:1646  */
     { (yyval.declarator_list) = append_declarator( NULL, (yyvsp[0].declarator) ); }
-#line 4842 "parser.tab.c" /* yacc.c:1648  */
+#line 4837 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 370:
-#line 1099 "parser.y" /* yacc.c:1648  */
+#line 1097 "parser.y" /* yacc.c:1646  */
     { (yyval.declarator_list) = append_declarator( (yyvsp[-2].declarator_list), (yyvsp[0].declarator) ); }
-#line 4848 "parser.tab.c" /* yacc.c:1648  */
+#line 4843 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 371:
-#line 1103 "parser.y" /* yacc.c:1648  */
+#line 1101 "parser.y" /* yacc.c:1646  */
     { (yyval.declarator) = (yyvsp[0].declarator); }
-#line 4854 "parser.tab.c" /* yacc.c:1648  */
+#line 4849 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 372:
-#line 1104 "parser.y" /* yacc.c:1648  */
+#line 1102 "parser.y" /* yacc.c:1646  */
     { (yyval.declarator) = (yyvsp[-2].declarator); (yyvsp[-2].declarator)->var->eval = (yyvsp[0].expr); }
-#line 4860 "parser.tab.c" /* yacc.c:1648  */
+#line 4855 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 373:
-#line 1108 "parser.y" /* yacc.c:1648  */
+#line 1106 "parser.y" /* yacc.c:1646  */
     { (yyval.num) = THREADING_APARTMENT; }
-#line 4866 "parser.tab.c" /* yacc.c:1648  */
+#line 4861 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 374:
-#line 1109 "parser.y" /* yacc.c:1648  */
+#line 1107 "parser.y" /* yacc.c:1646  */
     { (yyval.num) = THREADING_NEUTRAL; }
-#line 4872 "parser.tab.c" /* yacc.c:1648  */
+#line 4867 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 375:
-#line 1110 "parser.y" /* yacc.c:1648  */
+#line 1108 "parser.y" /* yacc.c:1646  */
     { (yyval.num) = THREADING_SINGLE; }
-#line 4878 "parser.tab.c" /* yacc.c:1648  */
+#line 4873 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 376:
-#line 1111 "parser.y" /* yacc.c:1648  */
+#line 1109 "parser.y" /* yacc.c:1646  */
     { (yyval.num) = THREADING_FREE; }
-#line 4884 "parser.tab.c" /* yacc.c:1648  */
+#line 4879 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 377:
-#line 1112 "parser.y" /* yacc.c:1648  */
+#line 1110 "parser.y" /* yacc.c:1646  */
     { (yyval.num) = THREADING_BOTH; }
-#line 4890 "parser.tab.c" /* yacc.c:1648  */
+#line 4885 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 378:
-#line 1116 "parser.y" /* yacc.c:1648  */
+#line 1114 "parser.y" /* yacc.c:1646  */
     { (yyval.num) = FC_RP; }
-#line 4896 "parser.tab.c" /* yacc.c:1648  */
+#line 4891 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 379:
-#line 1117 "parser.y" /* yacc.c:1648  */
+#line 1115 "parser.y" /* yacc.c:1646  */
     { (yyval.num) = FC_UP; }
-#line 4902 "parser.tab.c" /* yacc.c:1648  */
+#line 4897 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 380:
-#line 1118 "parser.y" /* yacc.c:1648  */
+#line 1116 "parser.y" /* yacc.c:1646  */
     { (yyval.num) = FC_FP; }
-#line 4908 "parser.tab.c" /* yacc.c:1648  */
+#line 4903 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 381:
-#line 1121 "parser.y" /* yacc.c:1648  */
+#line 1119 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = type_new_struct((yyvsp[-3].str), current_namespace, TRUE, (yyvsp[-1].var_list)); }
-#line 4914 "parser.tab.c" /* yacc.c:1648  */
+#line 4909 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 382:
-#line 1124 "parser.y" /* yacc.c:1648  */
+#line 1122 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = type_new_void(); }
-#line 4920 "parser.tab.c" /* yacc.c:1648  */
+#line 4915 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 383:
-#line 1125 "parser.y" /* yacc.c:1648  */
+#line 1123 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = find_type_or_error((yyvsp[0].str), 0); }
-#line 4926 "parser.tab.c" /* yacc.c:1648  */
+#line 4921 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 384:
-#line 1126 "parser.y" /* yacc.c:1648  */
+#line 1124 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = (yyvsp[0].type); }
-#line 4932 "parser.tab.c" /* yacc.c:1648  */
+#line 4927 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 385:
-#line 1127 "parser.y" /* yacc.c:1648  */
+#line 1125 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = (yyvsp[0].type); }
-#line 4938 "parser.tab.c" /* yacc.c:1648  */
+#line 4933 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 386:
-#line 1128 "parser.y" /* yacc.c:1648  */
+#line 1126 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = type_new_enum((yyvsp[0].str), current_namespace, FALSE, NULL); }
-#line 4944 "parser.tab.c" /* yacc.c:1648  */
+#line 4939 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 387:
-#line 1129 "parser.y" /* yacc.c:1648  */
+#line 1127 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = (yyvsp[0].type); }
-#line 4950 "parser.tab.c" /* yacc.c:1648  */
+#line 4945 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 388:
-#line 1130 "parser.y" /* yacc.c:1648  */
+#line 1128 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = type_new_struct((yyvsp[0].str), current_namespace, FALSE, NULL); }
-#line 4956 "parser.tab.c" /* yacc.c:1648  */
+#line 4951 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 389:
-#line 1131 "parser.y" /* yacc.c:1648  */
+#line 1129 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = (yyvsp[0].type); }
-#line 4962 "parser.tab.c" /* yacc.c:1648  */
+#line 4957 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 390:
-#line 1132 "parser.y" /* yacc.c:1648  */
+#line 1130 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = type_new_nonencapsulated_union((yyvsp[0].str), FALSE, NULL); }
-#line 4968 "parser.tab.c" /* yacc.c:1648  */
+#line 4963 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 391:
-#line 1133 "parser.y" /* yacc.c:1648  */
+#line 1131 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = make_safearray((yyvsp[-1].type)); }
-#line 4974 "parser.tab.c" /* yacc.c:1648  */
+#line 4969 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 392:
-#line 1137 "parser.y" /* yacc.c:1648  */
+#line 1135 "parser.y" /* yacc.c:1646  */
     { (yyvsp[-4].attr_list) = append_attribs((yyvsp[-4].attr_list), (yyvsp[-2].attr_list));
 						  reg_typedefs((yyvsp[-1].declspec), (yyvsp[0].declarator_list), check_typedef_attrs((yyvsp[-4].attr_list)));
 						  (yyval.statement) = make_statement_typedef((yyvsp[0].declarator_list));
 						}
-#line 4983 "parser.tab.c" /* yacc.c:1648  */
+#line 4978 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 393:
-#line 1144 "parser.y" /* yacc.c:1648  */
+#line 1142 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = type_new_nonencapsulated_union((yyvsp[-3].str), TRUE, (yyvsp[-1].var_list)); }
-#line 4989 "parser.tab.c" /* yacc.c:1648  */
+#line 4984 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 394:
-#line 1147 "parser.y" /* yacc.c:1648  */
+#line 1145 "parser.y" /* yacc.c:1646  */
     { (yyval.type) = type_new_encapsulated_union((yyvsp[-8].str), (yyvsp[-5].var), (yyvsp[-3].var), (yyvsp[-1].var_list)); }
-#line 4995 "parser.tab.c" /* yacc.c:1648  */
+#line 4990 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 395:
-#line 1151 "parser.y" /* yacc.c:1648  */
+#line 1149 "parser.y" /* yacc.c:1646  */
     { (yyval.num) = MAKEVERSION((yyvsp[0].num), 0); }
-#line 5001 "parser.tab.c" /* yacc.c:1648  */
+#line 4996 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 396:
-#line 1152 "parser.y" /* yacc.c:1648  */
+#line 1150 "parser.y" /* yacc.c:1646  */
     { (yyval.num) = MAKEVERSION((yyvsp[-2].num), (yyvsp[0].num)); }
-#line 5007 "parser.tab.c" /* yacc.c:1648  */
+#line 5002 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 397:
-#line 1153 "parser.y" /* yacc.c:1648  */
+#line 1151 "parser.y" /* yacc.c:1646  */
     { (yyval.num) = (yyvsp[0].num); }
-#line 5013 "parser.tab.c" /* yacc.c:1648  */
+#line 5008 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 402:
-#line 1166 "parser.y" /* yacc.c:1648  */
+#line 1164 "parser.y" /* yacc.c:1646  */
     { type_t *type = find_type_or_error((yyvsp[-1].str), 0);
                                                   type->attrs = append_attr_list(type->attrs, (yyvsp[-2].attr_list));
                                                 }
-#line 5021 "parser.tab.c" /* yacc.c:1648  */
+#line 5016 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 403:
-#line 1171 "parser.y" /* yacc.c:1648  */
+#line 1169 "parser.y" /* yacc.c:1646  */
     {  type_t *iface = find_type_or_error2((yyvsp[-3].str), 0);
                                                    if (type_get_type(iface) != TYPE_INTERFACE)
                                                        error_loc("%s is not an interface\n", iface->name);
                                                    iface->attrs = append_attr_list(iface->attrs, (yyvsp[-5].attr_list));
                                                 }
-#line 5031 "parser.tab.c" /* yacc.c:1648  */
+#line 5026 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 404:
-#line 1178 "parser.y" /* yacc.c:1648  */
+#line 1176 "parser.y" /* yacc.c:1646  */
     { (yyval.attr_list) = NULL; }
-#line 5037 "parser.tab.c" /* yacc.c:1648  */
+#line 5032 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 405:
-#line 1179 "parser.y" /* yacc.c:1648  */
+#line 1177 "parser.y" /* yacc.c:1646  */
     { (yyval.attr_list) = (yyvsp[-1].attr_list); }
-#line 5043 "parser.tab.c" /* yacc.c:1648  */
+#line 5038 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 406:
-#line 1182 "parser.y" /* yacc.c:1648  */
+#line 1180 "parser.y" /* yacc.c:1646  */
     { (yyval.attr_list) = append_attr(NULL, (yyvsp[0].attr)); }
-#line 5049 "parser.tab.c" /* yacc.c:1648  */
+#line 5044 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 407:
-#line 1183 "parser.y" /* yacc.c:1648  */
+#line 1181 "parser.y" /* yacc.c:1646  */
     { (yyval.attr_list) = append_attr((yyvsp[-2].attr_list), (yyvsp[0].attr)); }
-#line 5055 "parser.tab.c" /* yacc.c:1648  */
+#line 5050 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 408:
-#line 1186 "parser.y" /* yacc.c:1648  */
+#line 1184 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_ENCODE); }
-#line 5061 "parser.tab.c" /* yacc.c:1648  */
+#line 5056 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 409:
-#line 1187 "parser.y" /* yacc.c:1648  */
+#line 1185 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_DECODE); }
-#line 5067 "parser.tab.c" /* yacc.c:1648  */
+#line 5062 "parser.tab.c" /* yacc.c:1646  */
     break;
 
   case 410:
-#line 1188 "parser.y" /* yacc.c:1648  */
+#line 1186 "parser.y" /* yacc.c:1646  */
     { (yyval.attr) = make_attr(ATTR_EXPLICIT_HANDLE); }
-#line 5073 "parser.tab.c" /* yacc.c:1648  */
+#line 5068 "parser.tab.c" /* yacc.c:1646  */
     break;
 
 
-#line 5077 "parser.tab.c" /* yacc.c:1648  */
+#line 5072 "parser.tab.c" /* yacc.c:1646  */
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -5301,7 +5296,7 @@ yyreturn:
 #endif
   return yyresult;
 }
-#line 1190 "parser.y" /* yacc.c:1907  */
+#line 1188 "parser.y" /* yacc.c:1906  */
 
 
 static void decl_builtin_basic(const char *name, enum type_basic_type type)
@@ -5312,7 +5307,8 @@ static void decl_builtin_basic(const char *name, enum type_basic_type type)
 
 static void decl_builtin_alias(const char *name, type_t *t)
 {
-  reg_type(type_new_alias(t, name), name, NULL, 0);
+  decl_spec_t ds;
+  reg_type(type_new_alias(init_declspec(&ds, t), name), name, &global_namespace, 0);
 }
 
 void init_types(void)
@@ -5323,7 +5319,7 @@ void init_types(void)
   decl_builtin_basic("double", TYPE_BASIC_DOUBLE);
   decl_builtin_basic("error_status_t", TYPE_BASIC_ERROR_STATUS_T);
   decl_builtin_basic("handle_t", TYPE_BASIC_HANDLE);
-  decl_builtin_alias("boolean", type_new_basic(TYPE_BASIC_BYTE));
+  decl_builtin_alias("boolean", type_new_basic(TYPE_BASIC_CHAR));
 }
 
 static str_list_t *append_str(str_list_t *list, char *str)
@@ -5354,6 +5350,7 @@ static attr_list_t *append_attr(attr_list_t *list, attr_t *attr)
     LIST_FOR_EACH_ENTRY(attr_existing, list, attr_t, entry)
         if (attr_existing->type == attr->type)
         {
+            __builtin_trap();
             parser_warning("duplicate attribute %s\n", get_attr_display_name(attr->type));
             /* use the last attribute, like MIDL does */
             list_remove(&attr_existing->entry);
@@ -5413,53 +5410,73 @@ static attr_list_t *map_attrs(const attr_list_t *list, map_attrs_filter_t filter
   return new_list;
 }
 
-static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, attr_t *attr, enum storage_class stgclass)
+static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, enum storage_class stgclass, enum type_qualifier typequalifier, enum function_specifier funcspecifier)
 {
   decl_spec_t *declspec = left ? left : right;
   if (!declspec)
   {
     declspec = xmalloc(sizeof(*declspec));
     declspec->type = NULL;
-    declspec->attrs = NULL;
     declspec->stgclass = STG_NONE;
+    declspec->typequalifier = TYPE_QUALIFIER_NONE;
+    declspec->funcspecifier = FUNCTION_SPECIFIER_NONE;
   }
   declspec->type = type;
   if (left && declspec != left)
   {
-    declspec->attrs = append_attr_list(declspec->attrs, left->attrs);
     if (declspec->stgclass == STG_NONE)
       declspec->stgclass = left->stgclass;
     else if (left->stgclass != STG_NONE)
       error_loc("only one storage class can be specified\n");
+
+    if (declspec->typequalifier == TYPE_QUALIFIER_NONE)
+      declspec->typequalifier = left->typequalifier;
+    else if (left->typequalifier != TYPE_QUALIFIER_NONE)
+      error_loc("only one type qualifier can be specified\n");
+
+    if (declspec->funcspecifier == FUNCTION_SPECIFIER_NONE)
+      declspec->funcspecifier = left->funcspecifier;
+    else if (left->funcspecifier != FUNCTION_SPECIFIER_NONE)
+      error_loc("only one function specifier can be specified\n");
+
     assert(!left->type);
     free(left);
   }
   if (right && declspec != right)
   {
-    declspec->attrs = append_attr_list(declspec->attrs, right->attrs);
     if (declspec->stgclass == STG_NONE)
       declspec->stgclass = right->stgclass;
     else if (right->stgclass != STG_NONE)
       error_loc("only one storage class can be specified\n");
+
+    if (declspec->typequalifier == TYPE_QUALIFIER_NONE)
+      declspec->typequalifier = right->typequalifier;
+    else if (right->typequalifier != TYPE_QUALIFIER_NONE)
+      error_loc("only one type qualifier can be specified\n");
+
+    if (declspec->funcspecifier == FUNCTION_SPECIFIER_NONE)
+      declspec->funcspecifier = right->funcspecifier;
+    else if (right->funcspecifier != FUNCTION_SPECIFIER_NONE)
+      error_loc("only one function specifier can be specified\n");
+
     assert(!right->type);
     free(right);
   }
 
-  declspec->attrs = append_attr(declspec->attrs, attr);
   if (declspec->stgclass == STG_NONE)
     declspec->stgclass = stgclass;
   else if (stgclass != STG_NONE)
     error_loc("only one storage class can be specified\n");
 
-  /* apply attributes to type */
-  if (type && declspec->attrs)
-  {
-    attr_list_t *attrs;
-    declspec->type = duptype(type, 1);
-    attrs = map_attrs(type->attrs, NULL);
-    declspec->type->attrs = append_attr_list(attrs, declspec->attrs);
-    declspec->attrs = NULL;
-  }
+  if (declspec->typequalifier == TYPE_QUALIFIER_NONE)
+    declspec->typequalifier = typequalifier;
+  else if (typequalifier != TYPE_QUALIFIER_NONE)
+    error_loc("only one type qualifier can be specified\n");
+
+  if (declspec->funcspecifier == FUNCTION_SPECIFIER_NONE)
+    declspec->funcspecifier = funcspecifier;
+  else if (funcspecifier != FUNCTION_SPECIFIER_NONE)
+    error_loc("only one function specifier can be specified\n");
 
   return declspec;
 }
@@ -5545,6 +5562,7 @@ void clear_all_offsets(void)
 
 static void type_function_add_head_arg(type_t *type, var_t *arg)
 {
+    assert(type_get_type_detect_alias(type) == TYPE_FUNCTION);
     if (!type->details.function->args)
     {
         type->details.function->args = xmalloc( sizeof(*type->details.function->args) );
@@ -5589,31 +5607,60 @@ static int is_allowed_range_type(const type_t *type)
 static type_t *get_array_or_ptr_ref(type_t *type)
 {
     if (is_ptr(type))
-        return type_pointer_get_ref(type);
+        return type_pointer_get_ref_type(type);
     else if (is_array(type))
-        return type_array_get_element(type);
+        return type_array_get_element_type(type);
     return NULL;
 }
 
 static type_t *append_chain_type(type_t *chain, type_t *type)
 {
-    type_t *chain_type;
+    type_t *chain_type = NULL;
 
     if (!chain)
         return type;
     for (chain_type = chain; get_array_or_ptr_ref(chain_type); chain_type = get_array_or_ptr_ref(chain_type))
         ;
 
+    assert(!type_is_alias(chain_type));
     if (is_ptr(chain_type))
-        chain_type->details.pointer.ref = type;
+        chain_type->details.pointer.ref.type = type;
     else if (is_array(chain_type))
-        chain_type->details.array.elem = type;
+        chain_type->details.array.elem.type = type;
     else
         assert(0);
 
     return chain;
 }
 
+static decl_spec_t *append_chain_declspec(decl_spec_t *chain, type_t *type, enum type_qualifier typequalifier)
+{
+    type_t *chain_type = chain->type;
+    decl_spec_t *chain_declspec = NULL;
+
+    if (!chain_type)
+    {
+        chain->type = type;
+        chain->typequalifier = typequalifier;
+        return chain;
+    }
+
+    for(; get_array_or_ptr_ref(chain_type); chain_type = get_array_or_ptr_ref(chain_type))
+        ;
+
+    if (is_ptr(chain_type))
+        chain_declspec = &chain_type->details.pointer.ref;
+    else if (is_array(chain_type))
+        chain_declspec = &chain_type->details.array.elem;
+    else
+        assert(NULL);
+
+    chain_declspec->type = type;
+    chain_declspec->typequalifier = typequalifier;
+
+    return chain;
+}
+
 static warning_list_t *append_warning(warning_list_t *list, int num)
 {
     warning_t *entry;
@@ -5629,7 +5676,7 @@ static warning_list_t *append_warning(warning_list_t *list, int num)
     return list;
 }
 
-static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const declarator_t *decl,
+static var_t *declare_var(attr_list_t *attrs, decl_spec_t *declspec, const declarator_t *decl,
                        int top)
 {
   var_t *v = decl->var;
@@ -5638,58 +5685,74 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl
   expr_t *dim;
   type_t **ptype;
   type_t *func_type = decl ? decl->func_type : NULL;
-  type_t *type = decl_spec->type;
+  type_t *type = declspec->type;
 
-  if (is_attr(type->attrs, ATTR_INLINE))
-  {
+
+  if (declspec->funcspecifier == FUNCTION_SPECIFIER_INLINE) {
     if (!func_type)
       error_loc("inline attribute applied to non-function type\n");
     else
     {
-      type_t *t;
-      /* move inline attribute from return type node to function node */
-      for (t = func_type; is_ptr(t); t = type_pointer_get_ref(t))
-        ;
-      t->attrs = move_attr(t->attrs, type->attrs, ATTR_INLINE);
+      v->declspec.funcspecifier = declspec->funcspecifier;
     }
   }
 
-  /* add type onto the end of the pointers in pident->type */
-  v->type = append_chain_type(decl ? decl->type : NULL, type);
-  v->stgclass = decl_spec->stgclass;
+  /* if the var type is a pointerish, we need to move the type qualifier to the pointee's declspec
+   * unless the pointee already has const type qualifier*/
+  if (!decl)
+  {
+    /* simplest case, no pointers to deal with here */
+    v->declspec.typequalifier = declspec->typequalifier;
+  } else if (decl->bits)
+  {
+    /* dealing with a bitfield, generate bitfield and copy over typequalifier*/
+    v->declspec.type = type_new_bitfield(declspec->type, decl->bits);
+    v->declspec.typequalifier = declspec->typequalifier;
+  }
+  else
+  {
+    /* here we're dealing with a pointerish type chain, so we need to pull
+     * the typequalifier off of the declspec and stick them in the type's attr list
+     */
+    v->declspec.type = decl->declspec.type;
+    v->declspec.typequalifier = decl->declspec.typequalifier;
+    append_chain_declspec(&v->declspec, type, declspec->typequalifier);
+  }
+
+  v->declspec.stgclass = declspec->stgclass;
   v->attrs = attrs;
 
   /* check for pointer attribute being applied to non-pointer, non-array
    * type */
-  if (!is_array(v->type))
+  if (!is_array(v->declspec.type))
   {
     int ptr_attr = get_attrv(v->attrs, ATTR_POINTERTYPE);
     const type_t *ptr = NULL;
     /* pointer attributes on the left side of the type belong to the function
      * pointer, if one is being declared */
-    type_t **pt = func_type ? &func_type : &v->type;
+    type_t **pt = func_type ? &func_type : &v->declspec.type;
     for (ptr = *pt; ptr && !ptr_attr; )
     {
       ptr_attr = get_attrv(ptr->attrs, ATTR_POINTERTYPE);
       if (!ptr_attr && type_is_alias(ptr))
-        ptr = type_alias_get_aliasee(ptr);
+        ptr = type_alias_get_aliasee_type(ptr);
       else
         break;
     }
     if (is_ptr(ptr))
     {
       if (ptr_attr && ptr_attr != FC_UP &&
-          type_get_type(type_pointer_get_ref(ptr)) == TYPE_INTERFACE)
+          type_get_type(type_pointer_get_ref_type(ptr)) == TYPE_INTERFACE)
           warning_loc_info(&v->loc_info,
                            "%s: pointer attribute applied to interface "
                            "pointer type has no effect\n", v->name);
-      if (!ptr_attr && top && (*pt)->details.pointer.def_fc != FC_RP)
+      if (!ptr_attr && top && type_pointer_get_default_fc(*pt) != FC_RP)
       {
         /* FIXME: this is a horrible hack to cope with the issue that we
          * store an offset to the typeformat string in the type object, but
          * two typeformat strings may be written depending on whether the
          * pointer is a toplevel parameter or not */
-        *pt = duptype(*pt, 1);
+        *pt = dup_pointer_type(*pt);
       }
     }
     else if (ptr_attr)
@@ -5700,16 +5763,16 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl
   {
     type_t *t = type;
 
-    if (!is_ptr(v->type) && !is_array(v->type))
+    if (!is_ptr(v->declspec.type) && !is_array(v->declspec.type))
       error_loc("'%s': [string] attribute applied to non-pointer, non-array type\n",
                 v->name);
 
     for (;;)
     {
         if (is_ptr(t))
-            t = type_pointer_get_ref(t);
+            t = type_pointer_get_ref_type(t);
         else if (is_array(t))
-            t = type_array_get_element(t);
+            t = type_array_get_element_type(t);
         else
             break;
     }
@@ -5726,15 +5789,15 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl
 
   if (is_attr(v->attrs, ATTR_V1ENUM))
   {
-    if (type_get_type_detect_alias(v->type) != TYPE_ENUM)
+    if (type_get_type_detect_alias(v->declspec.type) != TYPE_ENUM)
       error_loc("'%s': [v1_enum] attribute applied to non-enum type\n", v->name);
   }
 
-  if (is_attr(v->attrs, ATTR_RANGE) && !is_allowed_range_type(v->type))
+  if (is_attr(v->attrs, ATTR_RANGE) && !is_allowed_range_type(v->declspec.type))
     error_loc("'%s': [range] attribute applied to non-integer type\n",
               v->name);
 
-  ptype = &v->type;
+  ptype = &v->declspec.type;
   if (sizes) LIST_FOR_EACH_ENTRY(dim, sizes, expr_t, entry)
   {
     if (dim->type != EXPR_VOID)
@@ -5747,7 +5810,7 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl
         else
           *ptype = type_new_array((*ptype)->name,
                                   type_array_get_element(*ptype), FALSE,
-                                  0, dim, NULL, 0);
+                                  0, dim, NULL, FC_RP);
       }
       else if (is_ptr(*ptype))
         *ptype = type_new_array((*ptype)->name, type_pointer_get_ref(*ptype), TRUE,
@@ -5756,15 +5819,16 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl
         error_loc("%s: size_is attribute applied to illegal type\n", v->name);
     }
 
+    assert(!type_is_alias(*ptype));
     if (is_ptr(*ptype))
-      ptype = &(*ptype)->details.pointer.ref;
+      ptype = &(*ptype)->details.pointer.ref.type;
     else if (is_array(*ptype))
-      ptype = &(*ptype)->details.array.elem;
+      ptype = &(*ptype)->details.array.elem.type;
     else
       error_loc("%s: too many expressions in size_is attribute\n", v->name);
   }
 
-  ptype = &v->type;
+  ptype = &v->declspec.type;
   if (lengs) LIST_FOR_EACH_ENTRY(dim, lengs, expr_t, entry)
   {
     if (dim->type != EXPR_VOID)
@@ -5782,10 +5846,11 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl
         error_loc("%s: length_is attribute applied to illegal type\n", v->name);
     }
 
+    assert(!type_is_alias(*ptype));
     if (is_ptr(*ptype))
-      ptype = &(*ptype)->details.pointer.ref;
+      ptype = &(*ptype)->details.pointer.ref.type;
     else if (is_array(*ptype))
-      ptype = &(*ptype)->details.array.elem;
+      ptype = &(*ptype)->details.array.elem.type;
     else
       error_loc("%s: too many expressions in length_is attribute\n", v->name);
   }
@@ -5796,29 +5861,31 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl
   if (func_type)
   {
     type_t *ft, *t;
-    type_t *return_type = v->type;
-    v->type = func_type;
-    for (ft = v->type; is_ptr(ft); ft = type_pointer_get_ref(ft))
+    type_t *return_type = v->declspec.type;
+    enum type_qualifier typequalifier = v->declspec.typequalifier;
+
+    v->declspec.type = func_type;
+    v->declspec.typequalifier = TYPE_QUALIFIER_NONE;
+    for (ft = v->declspec.type; is_ptr(ft); ft = type_pointer_get_ref_type(ft))
       ;
     assert(type_get_type_detect_alias(ft) == TYPE_FUNCTION);
     ft->details.function->retval = make_var(xstrdup("_RetVal"));
-    ft->details.function->retval->type = return_type;
+    ft->details.function->retval->declspec.type = return_type;
+    ft->details.function->retval->declspec.typequalifier = typequalifier;
+
     /* move calling convention attribute, if present, from pointer nodes to
      * function node */
-    for (t = v->type; is_ptr(t); t = type_pointer_get_ref(t))
+    for (t = v->declspec.type; is_ptr(t); t = type_pointer_get_ref_type(t))
       ft->attrs = move_attr(ft->attrs, t->attrs, ATTR_CALLCONV);
   }
   else
   {
     type_t *t;
-    for (t = v->type; is_ptr(t); t = type_pointer_get_ref(t))
+    for (t = v->declspec.type; is_ptr(t); t = type_pointer_get_ref_type(t))
       if (is_attr(t->attrs, ATTR_CALLCONV))
         error_loc("calling convention applied to non-function-pointer type\n");
   }
 
-  if (decl->bits)
-    v->type = type_new_bitfield(v->type, decl->bits);
-
   return v;
 }
 
@@ -5866,6 +5933,10 @@ var_list_t *append_var(var_list_t *list, var_t *var)
         list_init( list );
     }
     list_add_tail( list, &var->entry );
+
+    if (var->declspec.type)
+        var->declonly = !type_is_defined(var->declspec.type);
+
     return list;
 }
 
@@ -5885,11 +5956,11 @@ var_t *make_var(char *name)
 {
   var_t *v = xmalloc(sizeof(var_t));
   v->name = name;
-  v->type = NULL;
+  init_declspec(&v->declspec, NULL);
   v->attrs = NULL;
   v->eval = NULL;
-  v->stgclass = STG_NONE;
   init_loc_info(&v->loc_info);
+  v->declonly = TRUE;
   return v;
 }
 
@@ -5897,10 +5968,9 @@ static var_t *copy_var(var_t *src, char *name, map_attrs_filter_t attr_filter)
 {
   var_t *v = xmalloc(sizeof(var_t));
   v->name = name;
-  v->type = src->type;
+  v->declspec = src->declspec;
   v->attrs = map_attrs(src->attrs, attr_filter);
   v->eval = src->eval;
-  v->stgclass = src->stgclass;
   v->loc_info = src->loc_info;
   return v;
 }
@@ -5920,7 +5990,7 @@ static declarator_t *make_declarator(var_t *var)
 {
   declarator_t *d = xmalloc(sizeof(*d));
   d->var = var ? var : make_var(NULL);
-  d->type = NULL;
+  init_declspec(&d->declspec, NULL);
   d->func_type = NULL;
   d->bits = NULL;
   return d;
@@ -5928,7 +5998,15 @@ static declarator_t *make_declarator(var_t *var)
 
 static type_t *make_safearray(type_t *type)
 {
-  return type_new_array(NULL, type_new_alias(type, "SAFEARRAY"), TRUE, 0,
+  decl_spec_t aliasee_ds;
+  decl_spec_t element_ds;
+
+  init_declspec(&element_ds,
+    type_new_alias(
+      init_declspec(&aliasee_ds, type),
+      "SAFEARRAY"));
+
+  return type_new_array(NULL, &element_ds, TRUE, 0,
                         NULL, NULL, FC_RP);
 }
 
@@ -6018,15 +6096,16 @@ type_t *reg_type(type_t *type, const char *name, struct namespace *namespace, in
   nt->t = t;
   nt->next = namespace->type_hash[hash];
   namespace->type_hash[hash] = nt;
-  if ((t == tsSTRUCT || t == tsUNION))
+  if ((t == tsSTRUCT || t == tsUNION || t == tsENUM))
     fix_incomplete_types(type);
   return type;
 }
 
 static int is_incomplete(const type_t *t)
 {
-  return !t->defined &&
-    (type_get_type_detect_alias(t) == TYPE_STRUCT ||
+  return !type_is_defined(t) &&
+    (type_get_type_detect_alias(t) == TYPE_ENUM ||
+     type_get_type_detect_alias(t) == TYPE_STRUCT ||
      type_get_type_detect_alias(t) == TYPE_UNION ||
      type_get_type_detect_alias(t) == TYPE_ENCAPSULATED_UNION);
 }
@@ -6034,19 +6113,16 @@ static int is_incomplete(const type_t *t)
 void add_incomplete(type_t *t)
 {
   struct typenode *tn = xmalloc(sizeof *tn);
+  assert(is_incomplete(t));
   tn->type = t;
   list_add_tail(&incomplete_types, &tn->entry);
 }
 
 static void fix_type(type_t *t)
 {
-  if (type_is_alias(t) && is_incomplete(t)) {
-    type_t *ot = type_alias_get_aliasee(t);
-    fix_type(ot);
-    if (type_get_type_detect_alias(ot) == TYPE_STRUCT ||
-        type_get_type_detect_alias(ot) == TYPE_UNION ||
-        type_get_type_detect_alias(ot) == TYPE_ENCAPSULATED_UNION)
-      t->details.structure = ot->details.structure;
+  if (type_is_alias(t) && is_incomplete(t)) 
+  {
+    type_t *ot = type_alias_get_aliasee_type(t);
     t->defined = ot->defined;
   }
 }
@@ -6070,7 +6146,7 @@ static void fix_incomplete_types(type_t *complete_type)
   {
     if (type_is_equal(complete_type, tn->type))
     {
-      tn->type->details.structure = complete_type->details.structure;
+      tn->type->details = complete_type->details;
       list_remove(&tn->entry);
       free(tn);
     }
@@ -6094,7 +6170,13 @@ static type_t *reg_typedefs(decl_spec_t *decl_spec, declarator_list_t *decls, at
       type_get_type_detect_alias(type) == TYPE_ENCAPSULATED_UNION)
   {
     if (!type->name)
+    {
       type->name = gen_name();
+      /* the generated name will be used and this typedef excluded from the
+       * built typelib unless the typedef has the 'public' attribute, so add it here */
+      if (do_typelib && !is_attr(attrs, ATTR_PUBLIC))
+        attrs = append_attr(attrs, make_attr(ATTR_PUBLIC));
+    }
 
     /* replace existing attributes when generating a typelib */
     if (do_typelib)
@@ -6125,7 +6207,7 @@ static type_t *reg_typedefs(decl_spec_t *decl_spec, declarator_list_t *decls, at
                     cur->loc_info.line_number);
 
       name = declare_var(attrs, decl_spec, decl, 0);
-      cur = type_new_alias(name->type, name->name);
+      cur = type_new_alias(&name->declspec, name->name);
       cur->attrs = attrs;
 
       if (is_incomplete(cur))
@@ -6293,7 +6375,6 @@ struct allowed_attr allowed_attr[] =
     /* ATTR_CASE */                { 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "case" },
     /* ATTR_CODE */                { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "code" },
     /* ATTR_COMMSTATUS */          { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "comm_status" },
-    /* ATTR_CONST */               { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "const" },
     /* ATTR_CONTEXTHANDLE */       { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "context_handle" },
     /* ATTR_CONTROL */             { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, "control" },
     /* ATTR_DECODE */              { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "decode" },
@@ -6328,7 +6409,6 @@ struct allowed_attr allowed_attr[] =
     /* ATTR_IMMEDIATEBIND */       { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "immediatebind" },
     /* ATTR_IMPLICIT_HANDLE */     { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "implicit_handle" },
     /* ATTR_IN */                  { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "in" },
-    /* ATTR_INLINE */              { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inline" },
     /* ATTR_INPUTSYNC */           { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inputsync" },
     /* ATTR_LENGTHIS */            { 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, "length_is" },
     /* ATTR_LIBLCID */             { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "lcid" },
@@ -6400,10 +6480,10 @@ static attr_list_t *check_iface_attrs(const char *name, attr_list_t *attrs)
     if (attr->type == ATTR_IMPLICIT_HANDLE)
     {
         const var_t *var = attr->u.pval;
-        if (type_get_type( var->type) == TYPE_BASIC &&
-            type_basic_get_type( var->type ) == TYPE_BASIC_HANDLE)
+        if (type_get_type( var->declspec.type) == TYPE_BASIC &&
+            type_basic_get_type( var->declspec.type ) == TYPE_BASIC_HANDLE)
             continue;
-        if (is_aliaschain_attr( var->type, ATTR_HANDLE ))
+        if (is_aliaschain_attr( var->declspec.type, ATTR_HANDLE ))
             continue;
       error_loc("attribute %s requires a handle type in interface %s\n",
                 allowed_attr[attr->type].display_name, name);
@@ -6608,7 +6688,7 @@ static int is_ptr_guid_type(const type_t *type)
 
     /* second, make sure it is a pointer to something of size sizeof(GUID),
      * i.e. 16 bytes */
-    return (type_memsize(type_pointer_get_ref(type)) == 16);
+    return (type_memsize(type_pointer_get_ref_type(type)) == 16);
 }
 
 static void check_conformance_expr_list(const char *attr_name, const var_t *arg, const type_t *container_type, expr_list_t *expr_list)
@@ -6635,7 +6715,7 @@ static void check_remoting_fields(const var_t *var, type_t *type);
 static void check_field_common(const type_t *container_type,
                                const char *container_name, const var_t *arg)
 {
-    type_t *type = arg->type;
+    type_t *type = arg->declspec.type;
     int more_to_do;
     const char *container_type_name;
     const char *var_type;
@@ -6665,7 +6745,7 @@ static void check_field_common(const type_t *container_type,
     }
 
     if (is_attr(arg->attrs, ATTR_LENGTHIS) &&
-        (is_attr(arg->attrs, ATTR_STRING) || is_aliaschain_attr(arg->type, ATTR_STRING)))
+        (is_attr(arg->attrs, ATTR_STRING) || is_aliaschain_attr(arg->declspec.type, ATTR_STRING)))
         error_loc_info(&arg->loc_info,
                        "string and length_is specified for argument %s are mutually exclusive attributes\n",
                        arg->name);
@@ -6762,23 +6842,28 @@ static void check_field_common(const type_t *container_type,
         {
             const type_t *t = type;
             while (is_ptr(t))
-                t = type_pointer_get_ref(t);
+                t = type_pointer_get_ref_type(t);
             if (is_aliaschain_attr(t, ATTR_RANGE))
                 warning_loc_info(&arg->loc_info, "%s: range not verified for a string of ranged types\n", arg->name);
             break;
         }
         case TGT_POINTER:
-            type = type_pointer_get_ref(type);
+            type = type_pointer_get_ref_type(type);
             more_to_do = TRUE;
             break;
         case TGT_ARRAY:
-            type = type_array_get_element(type);
+            type = type_array_get_element_type(type);
             more_to_do = TRUE;
             break;
+        case TGT_ENUM:
+            type = type_get_real_type(type);
+            if(!type_is_complete(type))
+            {
+                error_loc_info(&arg->loc_info, "undefined type declaration enum %s\n", type->name);
+            }
         case TGT_USER_TYPE:
         case TGT_IFACE_POINTER:
         case TGT_BASIC:
-        case TGT_ENUM:
         case TGT_RANGE:
             /* nothing to do */
             break;
@@ -6803,13 +6888,18 @@ static void check_remoting_fields(const var_t *var, type_t *type)
         if (type_is_complete(type))
             fields = type_struct_get_fields(type);
         else
-            error_loc_info(&var->loc_info, "undefined type declaration %s\n", type->name);
+            error_loc_info(&var->loc_info, "undefined type declaration struct %s\n", type->name);
     }
     else if (type_get_type(type) == TYPE_UNION || type_get_type(type) == TYPE_ENCAPSULATED_UNION)
-        fields = type_union_get_cases(type);
+    {
+    	if (type_is_complete(type))
+            fields = type_union_get_cases(type);
+        else
+            error_loc_info(&var->loc_info, "undefined type declaration union %s\n", type->name);
+    }
 
     if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
-        if (field->type) check_field_common(type, type->name, field);
+        if (field->declspec.type) check_field_common(type, type->name, field);
 }
 
 /* checks that arguments for a function make sense for marshalling and unmarshalling */
@@ -6818,9 +6908,10 @@ static void check_remoting_args(const var_t *func)
     const char *funcname = func->name;
     const var_t *arg;
 
-    if (func->type->details.function->args) LIST_FOR_EACH_ENTRY( arg, func->type->details.function->args, const var_t, entry )
+    assert(type_get_type_detect_alias(func->declspec.type) == TYPE_FUNCTION);
+    if (func->declspec.type->details.function->args) LIST_FOR_EACH_ENTRY( arg, func->declspec.type->details.function->args, const var_t, entry )
     {
-        const type_t *type = arg->type;
+        const type_t *type = arg->declspec.type;
 
         /* check that [out] parameters have enough pointer levels */
         if (is_attr(arg->attrs, ATTR_OUT))
@@ -6860,16 +6951,16 @@ static void check_remoting_args(const var_t *func)
             }
         }
 
-        check_field_common(func->type, funcname, arg);
+        check_field_common(func->declspec.type, funcname, arg);
     }
 
-    if (type_get_type(type_function_get_rettype(func->type)) != TYPE_VOID)
+    if (type_get_type(type_function_get_rettype(func->declspec.type)) != TYPE_VOID)
     {
         var_t var;
         var = *func;
-        var.type = type_function_get_rettype(func->type);
+        var.declspec.type = type_function_get_rettype(func->declspec.type);
         var.name = xstrdup("return value");
-        check_field_common(func->type, funcname, &var);
+        check_field_common(func->declspec.type, funcname, &var);
         free(var.name);
     }
 }
@@ -6886,8 +6977,8 @@ static void add_explicit_handle_if_necessary(const type_t *iface, var_t *func)
          * function */
         var_t *idl_handle = make_var(xstrdup("IDL_handle"));
         idl_handle->attrs = append_attr(NULL, make_attr(ATTR_IN));
-        idl_handle->type = find_type_or_error("handle_t", 0);
-        type_function_add_head_arg(func->type, idl_handle);
+        idl_handle->declspec.type = find_type_or_error("handle_t", 0);
+        type_function_add_head_arg(func->declspec.type, idl_handle);
     }
 }
 
@@ -6952,6 +7043,7 @@ static void check_async_uuid(type_t *iface)
     type_t *async_iface;
     type_t *inherit;
 
+    assert(type_get_type_detect_alias(iface) == TYPE_INTERFACE);
     if (!is_attr(iface->attrs, ATTR_ASYNCUUID)) return;
 
     inherit = iface->details.iface->inherit;
@@ -6968,7 +7060,8 @@ static void check_async_uuid(type_t *iface)
         var_t *begin_func, *finish_func, *func = stmt->u.var, *arg;
         var_list_t *begin_args = NULL, *finish_args = NULL, *args;
 
-        args = func->type->details.function->args;
+        assert(type_get_type_detect_alias(func->declspec.type) == TYPE_FUNCTION);
+        args = func->declspec.type->details.function->args;
         if (args) LIST_FOR_EACH_ENTRY(arg, args, var_t, entry)
         {
             if (is_attr(arg->attrs, ATTR_IN) || !is_attr(arg->attrs, ATTR_OUT))
@@ -6978,15 +7071,15 @@ static void check_async_uuid(type_t *iface)
         }
 
         begin_func = copy_var(func, concat_str("Begin_", func->name), NULL);
-        begin_func->type = type_new_function(begin_args);
-        begin_func->type->attrs = func->attrs;
-        begin_func->type->details.function->retval = func->type->details.function->retval;
+        begin_func->declspec.type = type_new_function(begin_args);
+        begin_func->declspec.type->attrs = func->attrs;
+        begin_func->declspec.type->details.function->retval = func->declspec.type->details.function->retval;
         stmts = append_statement(stmts, make_statement_declaration(begin_func));
 
         finish_func = copy_var(func, concat_str("Finish_", func->name), NULL);
-        finish_func->type = type_new_function(finish_args);
-        finish_func->type->attrs = func->attrs;
-        finish_func->type->details.function->retval = func->type->details.function->retval;
+        finish_func->declspec.type = type_new_function(finish_args);
+        finish_func->declspec.type->attrs = func->attrs;
+        finish_func->declspec.type->details.function->retval = func->declspec.type->details.function->retval;
         stmts = append_statement(stmts, make_statement_declaration(finish_func));
     }
 
@@ -7026,6 +7119,7 @@ static void check_statements(const statement_list_t *stmts, int is_inside_librar
 static void check_all_user_types(const statement_list_t *stmts)
 {
   const statement_t *stmt;
+  const var_t *v;
 
   if (stmts) LIST_FOR_EACH_ENTRY(stmt, stmts, const statement_t, entry)
   {
@@ -7037,7 +7131,11 @@ static void check_all_user_types(const statement_list_t *stmts)
       const statement_t *stmt_func;
       STATEMENTS_FOR_EACH_FUNC(stmt_func, type_iface_get_stmts(stmt->u.type)) {
         const var_t *func = stmt_func->u.var;
-        check_for_additional_prototype_types(func->type->details.function->args);
+        assert(type_get_type_detect_alias(func->declspec.type) == TYPE_FUNCTION);
+        if (func->declspec.type->details.function->args)
+          LIST_FOR_EACH_ENTRY( v, func->declspec.type->details.function->args, const var_t, entry )
+            check_for_additional_prototype_types(v->declspec.type);
+        check_for_additional_prototype_types(type_function_get_rettype(func->declspec.type));
       }
     }
   }
@@ -7071,6 +7169,10 @@ static statement_t *make_statement_type_decl(type_t *type)
 {
     statement_t *stmt = make_statement(STMT_TYPE);
     stmt->u.type = type;
+    if (type_is_defined(type))
+    {
+        stmt->declonly = FALSE;
+    }
     return stmt;
 }
 
@@ -7085,16 +7187,16 @@ static statement_t *make_statement_declaration(var_t *var)
 {
     statement_t *stmt = make_statement(STMT_DECLARATION);
     stmt->u.var = var;
-    if (var->stgclass == STG_EXTERN && var->eval)
+    if (var->declspec.stgclass == STG_EXTERN && var->eval)
         warning("'%s' initialised and declared extern\n", var->name);
     if (is_const_decl(var))
     {
         if (var->eval)
             reg_const(var);
     }
-    else if (type_get_type(var->type) == TYPE_FUNCTION)
+    else if (type_get_type(var->declspec.type) == TYPE_FUNCTION)
         check_function_attrs(var->name, var->attrs);
-    else if (var->stgclass == STG_NONE || var->stgclass == STG_REGISTER)
+    else if (var->declspec.stgclass == STG_NONE || var->declspec.stgclass == STG_REGISTER)
         error_loc("instantiation of data is illegal\n");
     return stmt;
 }
@@ -7146,6 +7248,7 @@ static statement_t *make_statement_typedef(declarator_list_t *decls)
     declarator_t *decl, *next;
     statement_t *stmt;
     type_list_t **type_list;
+    int defined = TRUE;
 
     if (!decls) return NULL;
 
@@ -7157,6 +7260,18 @@ static statement_t *make_statement_typedef(declarator_list_t *decls)
     {
         var_t *var = decl->var;
         type_t *type = find_type_or_error(var->name, 0);
+
+        /* ensure that all of the types in this typedef statement have been defined
+         * before setting its declonly flag */
+        if (type_is_pointerish(type))
+        {
+            defined = defined & type_is_defined(type_get_pointer_chain_tail(type));
+        }
+        else
+        {
+            defined = defined & type_is_defined(type_get_real_type(type));
+        }
+
         *type_list = xmalloc(sizeof(type_list_t));
         (*type_list)->type = type;
         (*type_list)->next = NULL;
@@ -7166,6 +7281,7 @@ static statement_t *make_statement_typedef(declarator_list_t *decls)
         free(var);
     }
 
+    stmt->declonly = !defined;
     return stmt;
 }
 
@@ -7206,7 +7322,7 @@ void init_loc_info(loc_info_t *i)
 
 static void check_def(const type_t *t)
 {
-    if (t->defined)
+    if (type_is_defined(t))
         error_loc("%s: redefinition error; original definition was at %s:%d\n",
                   t->name, t->loc_info.input_name, t->loc_info.line_number);
 }
diff --git a/mingw-w64-tools/widl/src/parser.tab.h b/mingw-w64-tools/widl/src/parser.tab.h
index 09874726..fc7a8f4d 100644
--- a/mingw-w64-tools/widl/src/parser.tab.h
+++ b/mingw-w64-tools/widl/src/parser.tab.h
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.0.5.  */
+/* A Bison parser, made by GNU Bison 3.0.4.  */
 
 /* Bison interface for Yacc-like parsers in C
 
-   Copyright (C) 1984, 1989-1990, 2000-2015, 2018 Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -239,7 +239,7 @@ extern int parser_debug;
 
 union YYSTYPE
 {
-#line 142 "parser.y" /* yacc.c:1910  */
+#line 136 "parser.y" /* yacc.c:1909  */
 
 	attr_t *attr;
 	attr_list_t *attr_list;
@@ -266,8 +266,10 @@ union YYSTYPE
 	struct _import_t *import;
 	struct _decl_spec_t *declspec;
 	enum storage_class stgclass;
+	enum type_qualifier typequalifier;
+	enum function_specifier funcspecifier;
 
-#line 271 "parser.tab.h" /* yacc.c:1910  */
+#line 273 "parser.tab.h" /* yacc.c:1909  */
 };
 
 typedef union YYSTYPE YYSTYPE;
diff --git a/mingw-w64-tools/widl/src/parser.y b/mingw-w64-tools/widl/src/parser.y
index d9793941..64503ac1 100644
--- a/mingw-w64-tools/widl/src/parser.y
+++ b/mingw-w64-tools/widl/src/parser.y
@@ -52,13 +52,6 @@ struct _import_t
   int import_performed;
 };
 
-typedef struct _decl_spec_t
-{
-  type_t *type;
-  attr_list_t *attrs;
-  enum storage_class stgclass;
-} decl_spec_t;
-
 typelist_t incomplete_types = LIST_INIT(incomplete_types);
 
 static void fix_incomplete(void);
@@ -67,7 +60,7 @@ static void fix_incomplete_types(type_t *complete_type);
 static str_list_t *append_str(str_list_t *list, char *str);
 static attr_list_t *append_attr(attr_list_t *list, attr_t *attr);
 static attr_list_t *append_attr_list(attr_list_t *new_list, attr_list_t *old_list);
-static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, attr_t *attr, enum storage_class stgclass);
+static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, enum storage_class stgclass, enum type_qualifier typequalifier, enum function_specifier funcspecifier);
 static attr_t *make_attr(enum attr_type type);
 static attr_t *make_attrv(enum attr_type type, unsigned int val);
 static attr_t *make_attrp(enum attr_type type, void *val);
@@ -83,6 +76,7 @@ static declarator_t *make_declarator(var_t *var);
 static type_t *make_safearray(type_t *type);
 static typelib_t *make_library(const char *name, const attr_list_t *attrs);
 static type_t *append_chain_type(type_t *chain, type_t *type);
+static decl_spec_t *append_chain_declspec(decl_spec_t *chain, type_t *type, enum type_qualifier typequalifier);
 static warning_list_t *append_warning(warning_list_t *, int);
 
 static type_t *reg_typedefs(decl_spec_t *decl_spec, var_list_t *names, attr_list_t *attrs);
@@ -165,6 +159,8 @@ static typelib_t *current_typelib;
 	struct _import_t *import;
 	struct _decl_spec_t *declspec;
 	enum storage_class stgclass;
+	enum type_qualifier typequalifier;
+	enum function_specifier funcspecifier;
 }
 
 %token <str> aIDENTIFIER aPRAGMA
@@ -266,14 +262,16 @@ static typelib_t *current_typelib;
 %token tWCHAR tWIREMARSHAL
 %token tAPARTMENT tNEUTRAL tSINGLE tFREE tBOTH
 
-%type <attr> attribute type_qualifier function_specifier acf_attribute
-%type <attr_list> m_attributes attributes attrib_list m_type_qual_list
+%type <attr> attribute acf_attribute
+%type <attr_list> m_attributes attributes attrib_list
 %type <attr_list> acf_attributes acf_attribute_list
 %type <str_list> str_list
 %type <expr> m_expr expr expr_const expr_int_const array m_bitfield
 %type <expr_list> m_exprs /* exprs expr_list */ expr_list_int_const
 %type <ifinfo> interfacehdr
 %type <stgclass> storage_cls_spec
+%type <typequalifier> type_qualifier m_type_qual_bits
+%type <funcspecifier> function_specifier
 %type <declspec> decl_spec decl_spec_no_type m_decl_spec_no_type
 %type <type> inherit interface interfacedef interfacedec
 %type <type> dispinterface dispinterfacehdr dispinterfacedef
@@ -318,7 +316,7 @@ static typelib_t *current_typelib;
 %right '!' '~' CAST PPTR POS NEG ADDRESSOF tSIZEOF
 %left '.' MEMBERPTR '[' ']'
 
-%error-verbose
+%define parse.error verbose
 
 %%
 
@@ -651,10 +649,10 @@ enum_list: enum					{ if (!$1->eval)
 
 enum:	  ident '=' expr_int_const		{ $$ = reg_const($1);
 						  $$->eval = $3;
-                                                  $$->type = type_new_int(TYPE_BASIC_INT, 0);
+                                                  $$->declspec.type = type_new_int(TYPE_BASIC_INT, 0);
 						}
 	| ident					{ $$ = reg_const($1);
-                                                  $$->type = type_new_int(TYPE_BASIC_INT, 0);
+                                                  $$->declspec.type = type_new_int(TYPE_BASIC_INT, 0);
 						}
 	;
 
@@ -740,7 +738,7 @@ field:	  m_attributes decl_spec struct_declarator_list ';'
 						  $$ = set_var_types($1, $2, $3);
 						}
 	| m_attributes uniondef ';'		{ var_t *v = make_var(NULL);
-						  v->type = $2; v->attrs = $1;
+						  v->declspec.type = $2; v->attrs = $1;
 						  $$ = append_var(NULL, v);
 						}
 	;
@@ -764,13 +762,13 @@ s_field:  m_attributes decl_spec declarator	{ $$ = declare_var(check_field_attrs
 						  free($3);
 						}
 	| m_attributes structdef		{ var_t *v = make_var(NULL);
-						  v->type = $2; v->attrs = $1;
+						  v->declspec.type = $2; v->attrs = $1;
 						  $$ = v;
 						}
 	;
 
 funcdef: declaration				{ $$ = $1;
-						  if (type_get_type($$->type) != TYPE_FUNCTION)
+						  if (type_get_type($$->declspec.type) != TYPE_FUNCTION)
 						    error_loc("only methods may be declared inside the methods section of a dispinterface\n");
 						  check_function_attrs($$->name, $$->attrs);
 						}
@@ -955,20 +953,20 @@ storage_cls_spec:
 	;
 
 function_specifier:
-	  tINLINE				{ $$ = make_attr(ATTR_INLINE); }
+	  tINLINE				{ $$ = FUNCTION_SPECIFIER_INLINE; }
 	;
 
 type_qualifier:
-	  tCONST				{ $$ = make_attr(ATTR_CONST); }
+	  tCONST				{ $$ = TYPE_QUALIFIER_CONST; }
 	;
 
-m_type_qual_list:				{ $$ = NULL; }
-	| m_type_qual_list type_qualifier	{ $$ = append_attr($1, $2); }
+m_type_qual_bits:			{ $$ = TYPE_QUALIFIER_NONE; }
+	| m_type_qual_bits type_qualifier	{ $$ = $1 | $2; }
 	;
 
-decl_spec: type m_decl_spec_no_type		{ $$ = make_decl_spec($1, $2, NULL, NULL, STG_NONE); }
+decl_spec: type m_decl_spec_no_type		{ $$ = make_decl_spec($1, $2, NULL, STG_NONE, TYPE_QUALIFIER_NONE, FUNCTION_SPECIFIER_NONE); }
 	| decl_spec_no_type type m_decl_spec_no_type
-						{ $$ = make_decl_spec($2, $1, $3, NULL, STG_NONE); }
+						{ $$ = make_decl_spec($2, $1, $3, STG_NONE, TYPE_QUALIFIER_NONE, FUNCTION_SPECIFIER_NONE); }
 	;
 
 m_decl_spec_no_type:				{ $$ = NULL; }
@@ -976,44 +974,44 @@ m_decl_spec_no_type:				{ $$ = NULL; }
 	;
 
 decl_spec_no_type:
-	  type_qualifier m_decl_spec_no_type	{ $$ = make_decl_spec(NULL, $2, NULL, $1, STG_NONE); }
-	| function_specifier m_decl_spec_no_type  { $$ = make_decl_spec(NULL, $2, NULL, $1, STG_NONE); }
-	| storage_cls_spec m_decl_spec_no_type  { $$ = make_decl_spec(NULL, $2, NULL, NULL, $1); }
+	  type_qualifier m_decl_spec_no_type	{ $$ = make_decl_spec(NULL, $2, NULL, STG_NONE, $1, FUNCTION_SPECIFIER_NONE); }
+	| function_specifier m_decl_spec_no_type  { $$ = make_decl_spec(NULL, $2, NULL, STG_NONE, TYPE_QUALIFIER_NONE, $1); }
+	| storage_cls_spec m_decl_spec_no_type  { $$ = make_decl_spec(NULL, $2, NULL, $1, TYPE_QUALIFIER_NONE, FUNCTION_SPECIFIER_NONE); }
 	;
 
 declarator:
-	  '*' m_type_qual_list declarator %prec PPTR
-						{ $$ = $3; $$->type = append_chain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); }
+	  '*' m_type_qual_bits declarator %prec PPTR
+						{ $$ = $3; append_chain_declspec(&$$->declspec, type_new_pointer(pointer_default, NULL), $2); }
 	| callconv declarator			{ $$ = $2; if ($$->func_type) $$->func_type->attrs = append_attr($$->func_type->attrs, make_attrp(ATTR_CALLCONV, $1));
-						           else if ($$->type) $$->type->attrs = append_attr($$->type->attrs, make_attrp(ATTR_CALLCONV, $1)); }
+						           else if ($$->declspec.type) $$->declspec.type->attrs = append_attr($$->declspec.type->attrs, make_attrp(ATTR_CALLCONV, $1)); }
 	| direct_declarator
 	;
 
 direct_declarator:
 	  ident					{ $$ = make_declarator($1); }
 	| '(' declarator ')'			{ $$ = $2; }
-	| direct_declarator array		{ $$ = $1; $$->type = append_array($$->type, $2); }
+	| direct_declarator array		{ $$ = $1; $$->declspec.type = append_array($$->declspec.type, $2); }
 	| direct_declarator '(' m_args ')'	{ $$ = $1;
-						  $$->func_type = append_chain_type($$->type, type_new_function($3));
-						  $$->type = NULL;
+						  $$->func_type = append_chain_type($$->declspec.type, type_new_function($3));
+						  $$->declspec.type = NULL;
 						}
 	;
 
 /* abstract declarator */
 abstract_declarator:
-	  '*' m_type_qual_list m_abstract_declarator %prec PPTR
-						{ $$ = $3; $$->type = append_chain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); }
+	  '*' m_type_qual_bits m_abstract_declarator %prec PPTR
+						{ $$ = $3; append_chain_declspec(&$$->declspec, type_new_pointer(pointer_default, NULL), $2); }
 	| callconv m_abstract_declarator	{ $$ = $2; if ($$->func_type) $$->func_type->attrs = append_attr($$->func_type->attrs, make_attrp(ATTR_CALLCONV, $1));
-						           else if ($$->type) $$->type->attrs = append_attr($$->type->attrs, make_attrp(ATTR_CALLCONV, $1)); }
+						           else if ($$->declspec.type) $$->declspec.type->attrs = append_attr($$->declspec.type->attrs, make_attrp(ATTR_CALLCONV, $1)); }
 	| abstract_direct_declarator
 	;
 
 /* abstract declarator without accepting direct declarator */
 abstract_declarator_no_direct:
-	  '*' m_type_qual_list m_any_declarator %prec PPTR
-						{ $$ = $3; $$->type = append_chain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); }
+	  '*' m_type_qual_bits m_any_declarator %prec PPTR
+						{ $$ = $3; append_chain_declspec(&$$->declspec, type_new_pointer(pointer_default, NULL), $2); }
 	| callconv m_any_declarator		{ $$ = $2; if ($$->func_type) $$->func_type->attrs = append_attr($$->func_type->attrs, make_attrp(ATTR_CALLCONV, $1));
-						           else if ($$->type) $$->type->attrs = append_attr($$->type->attrs, make_attrp(ATTR_CALLCONV, $1)); }
+						           else if ($$->declspec.type) $$->declspec.type->attrs = append_attr($$->declspec.type->attrs, make_attrp(ATTR_CALLCONV, $1)); }
 	;
 
 /* abstract declarator or empty */
@@ -1024,33 +1022,33 @@ m_abstract_declarator: 				{ $$ = make_declarator(NULL); }
 /* abstract direct declarator */
 abstract_direct_declarator:
 	  '(' abstract_declarator_no_direct ')'	{ $$ = $2; }
-	| abstract_direct_declarator array	{ $$ = $1; $$->type = append_array($$->type, $2); }
-	| array					{ $$ = make_declarator(NULL); $$->type = append_array($$->type, $1); }
+	| abstract_direct_declarator array	{ $$ = $1; $$->declspec.type = append_array($$->declspec.type, $2); }
+	| array					{ $$ = make_declarator(NULL); $$->declspec.type = append_array($$->declspec.type, $1); }
 	| '(' m_args ')'
 						{ $$ = make_declarator(NULL);
-						  $$->func_type = append_chain_type($$->type, type_new_function($2));
-						  $$->type = NULL;
+						  $$->func_type = append_chain_type($$->declspec.type, type_new_function($2));
+						  $$->declspec.type = NULL;
 						}
 	| abstract_direct_declarator '(' m_args ')'
 						{ $$ = $1;
-						  $$->func_type = append_chain_type($$->type, type_new_function($3));
-						  $$->type = NULL;
+						  $$->func_type = append_chain_type($$->declspec.type, type_new_function($3));
+						  $$->declspec.type = NULL;
 						}
 	;
 
 /* abstract or non-abstract declarator */
 any_declarator:
-	  '*' m_type_qual_list m_any_declarator %prec PPTR
-						{ $$ = $3; $$->type = append_chain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); }
-	| callconv m_any_declarator		{ $$ = $2; $$->type->attrs = append_attr($$->type->attrs, make_attrp(ATTR_CALLCONV, $1)); }
+	  '*' m_type_qual_bits m_any_declarator %prec PPTR
+						{ $$ = $3; append_chain_declspec(&$$->declspec, type_new_pointer(pointer_default, NULL), $2); }
+	| callconv m_any_declarator		{ $$ = $2; $$->declspec.type->attrs = append_attr($$->declspec.type->attrs, make_attrp(ATTR_CALLCONV, $1)); }
 	| any_direct_declarator
 	;
 
 /* abstract or non-abstract declarator without accepting direct declarator */
 any_declarator_no_direct:
-	  '*' m_type_qual_list m_any_declarator %prec PPTR
-						{ $$ = $3; $$->type = append_chain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); }
-	| callconv m_any_declarator		{ $$ = $2; $$->type->attrs = append_attr($$->type->attrs, make_attrp(ATTR_CALLCONV, $1)); }
+	  '*' m_type_qual_bits m_any_declarator %prec PPTR
+						{ $$ = $3; append_chain_declspec(&$$->declspec, type_new_pointer(pointer_default, NULL), $2); }
+	| callconv m_any_declarator		{ $$ = $2; $$->declspec.type->attrs = append_attr($$->declspec.type->attrs, make_attrp(ATTR_CALLCONV, $1)); }
 	;
 
 /* abstract or non-abstract declarator or empty */
@@ -1064,17 +1062,17 @@ m_any_declarator: 				{ $$ = make_declarator(NULL); }
 any_direct_declarator:
 	  ident					{ $$ = make_declarator($1); }
 	| '(' any_declarator_no_direct ')'	{ $$ = $2; }
-	| any_direct_declarator array		{ $$ = $1; $$->type = append_array($$->type, $2); }
-	| array					{ $$ = make_declarator(NULL); $$->type = append_array($$->type, $1); }
+	| any_direct_declarator array		{ $$ = $1; $$->declspec.type = append_array($$->declspec.type, $2); }
+	| array					{ $$ = make_declarator(NULL); $$->declspec.type = append_array($$->declspec.type, $1); }
 	| '(' m_args ')'
 						{ $$ = make_declarator(NULL);
-						  $$->func_type = append_chain_type($$->type, type_new_function($2));
-						  $$->type = NULL;
+						  $$->func_type = append_chain_type($$->declspec.type, type_new_function($2));
+						  $$->declspec.type = NULL;
 						}
 	| any_direct_declarator '(' m_args ')'
 						{ $$ = $1;
-						  $$->func_type = append_chain_type($$->type, type_new_function($3));
-						  $$->type = NULL;
+						  $$->func_type = append_chain_type($$->declspec.type, type_new_function($3));
+						  $$->declspec.type = NULL;
 						}
 	;
 
@@ -1197,7 +1195,8 @@ static void decl_builtin_basic(const char *name, enum type_basic_type type)
 
 static void decl_builtin_alias(const char *name, type_t *t)
 {
-  reg_type(type_new_alias(t, name), name, NULL, 0);
+  decl_spec_t ds;
+  reg_type(type_new_alias(init_declspec(&ds, t), name), name, &global_namespace, 0);
 }
 
 void init_types(void)
@@ -1208,7 +1207,7 @@ void init_types(void)
   decl_builtin_basic("double", TYPE_BASIC_DOUBLE);
   decl_builtin_basic("error_status_t", TYPE_BASIC_ERROR_STATUS_T);
   decl_builtin_basic("handle_t", TYPE_BASIC_HANDLE);
-  decl_builtin_alias("boolean", type_new_basic(TYPE_BASIC_BYTE));
+  decl_builtin_alias("boolean", type_new_basic(TYPE_BASIC_CHAR));
 }
 
 static str_list_t *append_str(str_list_t *list, char *str)
@@ -1239,6 +1238,7 @@ static attr_list_t *append_attr(attr_list_t *list, attr_t *attr)
     LIST_FOR_EACH_ENTRY(attr_existing, list, attr_t, entry)
         if (attr_existing->type == attr->type)
         {
+            __builtin_trap();
             parser_warning("duplicate attribute %s\n", get_attr_display_name(attr->type));
             /* use the last attribute, like MIDL does */
             list_remove(&attr_existing->entry);
@@ -1298,53 +1298,73 @@ static attr_list_t *map_attrs(const attr_list_t *list, map_attrs_filter_t filter
   return new_list;
 }
 
-static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, attr_t *attr, enum storage_class stgclass)
+static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, enum storage_class stgclass, enum type_qualifier typequalifier, enum function_specifier funcspecifier)
 {
   decl_spec_t *declspec = left ? left : right;
   if (!declspec)
   {
     declspec = xmalloc(sizeof(*declspec));
     declspec->type = NULL;
-    declspec->attrs = NULL;
     declspec->stgclass = STG_NONE;
+    declspec->typequalifier = TYPE_QUALIFIER_NONE;
+    declspec->funcspecifier = FUNCTION_SPECIFIER_NONE;
   }
   declspec->type = type;
   if (left && declspec != left)
   {
-    declspec->attrs = append_attr_list(declspec->attrs, left->attrs);
     if (declspec->stgclass == STG_NONE)
       declspec->stgclass = left->stgclass;
     else if (left->stgclass != STG_NONE)
       error_loc("only one storage class can be specified\n");
+
+    if (declspec->typequalifier == TYPE_QUALIFIER_NONE)
+      declspec->typequalifier = left->typequalifier;
+    else if (left->typequalifier != TYPE_QUALIFIER_NONE)
+      error_loc("only one type qualifier can be specified\n");
+
+    if (declspec->funcspecifier == FUNCTION_SPECIFIER_NONE)
+      declspec->funcspecifier = left->funcspecifier;
+    else if (left->funcspecifier != FUNCTION_SPECIFIER_NONE)
+      error_loc("only one function specifier can be specified\n");
+
     assert(!left->type);
     free(left);
   }
   if (right && declspec != right)
   {
-    declspec->attrs = append_attr_list(declspec->attrs, right->attrs);
     if (declspec->stgclass == STG_NONE)
       declspec->stgclass = right->stgclass;
     else if (right->stgclass != STG_NONE)
       error_loc("only one storage class can be specified\n");
+
+    if (declspec->typequalifier == TYPE_QUALIFIER_NONE)
+      declspec->typequalifier = right->typequalifier;
+    else if (right->typequalifier != TYPE_QUALIFIER_NONE)
+      error_loc("only one type qualifier can be specified\n");
+
+    if (declspec->funcspecifier == FUNCTION_SPECIFIER_NONE)
+      declspec->funcspecifier = right->funcspecifier;
+    else if (right->funcspecifier != FUNCTION_SPECIFIER_NONE)
+      error_loc("only one function specifier can be specified\n");
+
     assert(!right->type);
     free(right);
   }
 
-  declspec->attrs = append_attr(declspec->attrs, attr);
   if (declspec->stgclass == STG_NONE)
     declspec->stgclass = stgclass;
   else if (stgclass != STG_NONE)
     error_loc("only one storage class can be specified\n");
 
-  /* apply attributes to type */
-  if (type && declspec->attrs)
-  {
-    attr_list_t *attrs;
-    declspec->type = duptype(type, 1);
-    attrs = map_attrs(type->attrs, NULL);
-    declspec->type->attrs = append_attr_list(attrs, declspec->attrs);
-    declspec->attrs = NULL;
-  }
+  if (declspec->typequalifier == TYPE_QUALIFIER_NONE)
+    declspec->typequalifier = typequalifier;
+  else if (typequalifier != TYPE_QUALIFIER_NONE)
+    error_loc("only one type qualifier can be specified\n");
+
+  if (declspec->funcspecifier == FUNCTION_SPECIFIER_NONE)
+    declspec->funcspecifier = funcspecifier;
+  else if (funcspecifier != FUNCTION_SPECIFIER_NONE)
+    error_loc("only one function specifier can be specified\n");
 
   return declspec;
 }
@@ -1430,6 +1450,7 @@ void clear_all_offsets(void)
 
 static void type_function_add_head_arg(type_t *type, var_t *arg)
 {
+    assert(type_get_type_detect_alias(type) == TYPE_FUNCTION);
     if (!type->details.function->args)
     {
         type->details.function->args = xmalloc( sizeof(*type->details.function->args) );
@@ -1474,31 +1495,60 @@ static int is_allowed_range_type(const type_t *type)
 static type_t *get_array_or_ptr_ref(type_t *type)
 {
     if (is_ptr(type))
-        return type_pointer_get_ref(type);
+        return type_pointer_get_ref_type(type);
     else if (is_array(type))
-        return type_array_get_element(type);
+        return type_array_get_element_type(type);
     return NULL;
 }
 
 static type_t *append_chain_type(type_t *chain, type_t *type)
 {
-    type_t *chain_type;
+    type_t *chain_type = NULL;
 
     if (!chain)
         return type;
     for (chain_type = chain; get_array_or_ptr_ref(chain_type); chain_type = get_array_or_ptr_ref(chain_type))
         ;
 
+    assert(!type_is_alias(chain_type));
     if (is_ptr(chain_type))
-        chain_type->details.pointer.ref = type;
+        chain_type->details.pointer.ref.type = type;
     else if (is_array(chain_type))
-        chain_type->details.array.elem = type;
+        chain_type->details.array.elem.type = type;
     else
         assert(0);
 
     return chain;
 }
 
+static decl_spec_t *append_chain_declspec(decl_spec_t *chain, type_t *type, enum type_qualifier typequalifier)
+{
+    type_t *chain_type = chain->type;
+    decl_spec_t *chain_declspec = NULL;
+
+    if (!chain_type)
+    {
+        chain->type = type;
+        chain->typequalifier = typequalifier;
+        return chain;
+    }
+
+    for(; get_array_or_ptr_ref(chain_type); chain_type = get_array_or_ptr_ref(chain_type))
+        ;
+
+    if (is_ptr(chain_type))
+        chain_declspec = &chain_type->details.pointer.ref;
+    else if (is_array(chain_type))
+        chain_declspec = &chain_type->details.array.elem;
+    else
+        assert(NULL);
+
+    chain_declspec->type = type;
+    chain_declspec->typequalifier = typequalifier;
+
+    return chain;
+}
+
 static warning_list_t *append_warning(warning_list_t *list, int num)
 {
     warning_t *entry;
@@ -1514,7 +1564,7 @@ static warning_list_t *append_warning(warning_list_t *list, int num)
     return list;
 }
 
-static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const declarator_t *decl,
+static var_t *declare_var(attr_list_t *attrs, decl_spec_t *declspec, const declarator_t *decl,
                        int top)
 {
   var_t *v = decl->var;
@@ -1523,58 +1573,74 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl
   expr_t *dim;
   type_t **ptype;
   type_t *func_type = decl ? decl->func_type : NULL;
-  type_t *type = decl_spec->type;
+  type_t *type = declspec->type;
 
-  if (is_attr(type->attrs, ATTR_INLINE))
-  {
+
+  if (declspec->funcspecifier == FUNCTION_SPECIFIER_INLINE) {
     if (!func_type)
       error_loc("inline attribute applied to non-function type\n");
     else
     {
-      type_t *t;
-      /* move inline attribute from return type node to function node */
-      for (t = func_type; is_ptr(t); t = type_pointer_get_ref(t))
-        ;
-      t->attrs = move_attr(t->attrs, type->attrs, ATTR_INLINE);
+      v->declspec.funcspecifier = declspec->funcspecifier;
     }
   }
 
-  /* add type onto the end of the pointers in pident->type */
-  v->type = append_chain_type(decl ? decl->type : NULL, type);
-  v->stgclass = decl_spec->stgclass;
+  /* if the var type is a pointerish, we need to move the type qualifier to the pointee's declspec
+   * unless the pointee already has const type qualifier*/
+  if (!decl)
+  {
+    /* simplest case, no pointers to deal with here */
+    v->declspec.typequalifier = declspec->typequalifier;
+  } else if (decl->bits)
+  {
+    /* dealing with a bitfield, generate bitfield and copy over typequalifier*/
+    v->declspec.type = type_new_bitfield(declspec->type, decl->bits);
+    v->declspec.typequalifier = declspec->typequalifier;
+  }
+  else
+  {
+    /* here we're dealing with a pointerish type chain, so we need to pull
+     * the typequalifier off of the declspec and stick them in the type's attr list
+     */
+    v->declspec.type = decl->declspec.type;
+    v->declspec.typequalifier = decl->declspec.typequalifier;
+    append_chain_declspec(&v->declspec, type, declspec->typequalifier);
+  }
+
+  v->declspec.stgclass = declspec->stgclass;
   v->attrs = attrs;
 
   /* check for pointer attribute being applied to non-pointer, non-array
    * type */
-  if (!is_array(v->type))
+  if (!is_array(v->declspec.type))
   {
     int ptr_attr = get_attrv(v->attrs, ATTR_POINTERTYPE);
     const type_t *ptr = NULL;
     /* pointer attributes on the left side of the type belong to the function
      * pointer, if one is being declared */
-    type_t **pt = func_type ? &func_type : &v->type;
+    type_t **pt = func_type ? &func_type : &v->declspec.type;
     for (ptr = *pt; ptr && !ptr_attr; )
     {
       ptr_attr = get_attrv(ptr->attrs, ATTR_POINTERTYPE);
       if (!ptr_attr && type_is_alias(ptr))
-        ptr = type_alias_get_aliasee(ptr);
+        ptr = type_alias_get_aliasee_type(ptr);
       else
         break;
     }
     if (is_ptr(ptr))
     {
       if (ptr_attr && ptr_attr != FC_UP &&
-          type_get_type(type_pointer_get_ref(ptr)) == TYPE_INTERFACE)
+          type_get_type(type_pointer_get_ref_type(ptr)) == TYPE_INTERFACE)
           warning_loc_info(&v->loc_info,
                            "%s: pointer attribute applied to interface "
                            "pointer type has no effect\n", v->name);
-      if (!ptr_attr && top && (*pt)->details.pointer.def_fc != FC_RP)
+      if (!ptr_attr && top && type_pointer_get_default_fc(*pt) != FC_RP)
       {
         /* FIXME: this is a horrible hack to cope with the issue that we
          * store an offset to the typeformat string in the type object, but
          * two typeformat strings may be written depending on whether the
          * pointer is a toplevel parameter or not */
-        *pt = duptype(*pt, 1);
+        *pt = dup_pointer_type(*pt);
       }
     }
     else if (ptr_attr)
@@ -1585,16 +1651,16 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl
   {
     type_t *t = type;
 
-    if (!is_ptr(v->type) && !is_array(v->type))
+    if (!is_ptr(v->declspec.type) && !is_array(v->declspec.type))
       error_loc("'%s': [string] attribute applied to non-pointer, non-array type\n",
                 v->name);
 
     for (;;)
     {
         if (is_ptr(t))
-            t = type_pointer_get_ref(t);
+            t = type_pointer_get_ref_type(t);
         else if (is_array(t))
-            t = type_array_get_element(t);
+            t = type_array_get_element_type(t);
         else
             break;
     }
@@ -1611,15 +1677,15 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl
 
   if (is_attr(v->attrs, ATTR_V1ENUM))
   {
-    if (type_get_type_detect_alias(v->type) != TYPE_ENUM)
+    if (type_get_type_detect_alias(v->declspec.type) != TYPE_ENUM)
       error_loc("'%s': [v1_enum] attribute applied to non-enum type\n", v->name);
   }
 
-  if (is_attr(v->attrs, ATTR_RANGE) && !is_allowed_range_type(v->type))
+  if (is_attr(v->attrs, ATTR_RANGE) && !is_allowed_range_type(v->declspec.type))
     error_loc("'%s': [range] attribute applied to non-integer type\n",
               v->name);
 
-  ptype = &v->type;
+  ptype = &v->declspec.type;
   if (sizes) LIST_FOR_EACH_ENTRY(dim, sizes, expr_t, entry)
   {
     if (dim->type != EXPR_VOID)
@@ -1632,7 +1698,7 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl
         else
           *ptype = type_new_array((*ptype)->name,
                                   type_array_get_element(*ptype), FALSE,
-                                  0, dim, NULL, 0);
+                                  0, dim, NULL, FC_RP);
       }
       else if (is_ptr(*ptype))
         *ptype = type_new_array((*ptype)->name, type_pointer_get_ref(*ptype), TRUE,
@@ -1641,15 +1707,16 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl
         error_loc("%s: size_is attribute applied to illegal type\n", v->name);
     }
 
+    assert(!type_is_alias(*ptype));
     if (is_ptr(*ptype))
-      ptype = &(*ptype)->details.pointer.ref;
+      ptype = &(*ptype)->details.pointer.ref.type;
     else if (is_array(*ptype))
-      ptype = &(*ptype)->details.array.elem;
+      ptype = &(*ptype)->details.array.elem.type;
     else
       error_loc("%s: too many expressions in size_is attribute\n", v->name);
   }
 
-  ptype = &v->type;
+  ptype = &v->declspec.type;
   if (lengs) LIST_FOR_EACH_ENTRY(dim, lengs, expr_t, entry)
   {
     if (dim->type != EXPR_VOID)
@@ -1667,10 +1734,11 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl
         error_loc("%s: length_is attribute applied to illegal type\n", v->name);
     }
 
+    assert(!type_is_alias(*ptype));
     if (is_ptr(*ptype))
-      ptype = &(*ptype)->details.pointer.ref;
+      ptype = &(*ptype)->details.pointer.ref.type;
     else if (is_array(*ptype))
-      ptype = &(*ptype)->details.array.elem;
+      ptype = &(*ptype)->details.array.elem.type;
     else
       error_loc("%s: too many expressions in length_is attribute\n", v->name);
   }
@@ -1681,29 +1749,31 @@ static var_t *declare_var(attr_list_t *attrs, decl_spec_t *decl_spec, const decl
   if (func_type)
   {
     type_t *ft, *t;
-    type_t *return_type = v->type;
-    v->type = func_type;
-    for (ft = v->type; is_ptr(ft); ft = type_pointer_get_ref(ft))
+    type_t *return_type = v->declspec.type;
+    enum type_qualifier typequalifier = v->declspec.typequalifier;
+
+    v->declspec.type = func_type;
+    v->declspec.typequalifier = TYPE_QUALIFIER_NONE;
+    for (ft = v->declspec.type; is_ptr(ft); ft = type_pointer_get_ref_type(ft))
       ;
     assert(type_get_type_detect_alias(ft) == TYPE_FUNCTION);
     ft->details.function->retval = make_var(xstrdup("_RetVal"));
-    ft->details.function->retval->type = return_type;
+    ft->details.function->retval->declspec.type = return_type;
+    ft->details.function->retval->declspec.typequalifier = typequalifier;
+
     /* move calling convention attribute, if present, from pointer nodes to
      * function node */
-    for (t = v->type; is_ptr(t); t = type_pointer_get_ref(t))
+    for (t = v->declspec.type; is_ptr(t); t = type_pointer_get_ref_type(t))
       ft->attrs = move_attr(ft->attrs, t->attrs, ATTR_CALLCONV);
   }
   else
   {
     type_t *t;
-    for (t = v->type; is_ptr(t); t = type_pointer_get_ref(t))
+    for (t = v->declspec.type; is_ptr(t); t = type_pointer_get_ref_type(t))
       if (is_attr(t->attrs, ATTR_CALLCONV))
         error_loc("calling convention applied to non-function-pointer type\n");
   }
 
-  if (decl->bits)
-    v->type = type_new_bitfield(v->type, decl->bits);
-
   return v;
 }
 
@@ -1751,6 +1821,10 @@ var_list_t *append_var(var_list_t *list, var_t *var)
         list_init( list );
     }
     list_add_tail( list, &var->entry );
+
+    if (var->declspec.type)
+        var->declonly = !type_is_defined(var->declspec.type);
+
     return list;
 }
 
@@ -1770,11 +1844,11 @@ var_t *make_var(char *name)
 {
   var_t *v = xmalloc(sizeof(var_t));
   v->name = name;
-  v->type = NULL;
+  init_declspec(&v->declspec, NULL);
   v->attrs = NULL;
   v->eval = NULL;
-  v->stgclass = STG_NONE;
   init_loc_info(&v->loc_info);
+  v->declonly = TRUE;
   return v;
 }
 
@@ -1782,10 +1856,9 @@ static var_t *copy_var(var_t *src, char *name, map_attrs_filter_t attr_filter)
 {
   var_t *v = xmalloc(sizeof(var_t));
   v->name = name;
-  v->type = src->type;
+  v->declspec = src->declspec;
   v->attrs = map_attrs(src->attrs, attr_filter);
   v->eval = src->eval;
-  v->stgclass = src->stgclass;
   v->loc_info = src->loc_info;
   return v;
 }
@@ -1805,7 +1878,7 @@ static declarator_t *make_declarator(var_t *var)
 {
   declarator_t *d = xmalloc(sizeof(*d));
   d->var = var ? var : make_var(NULL);
-  d->type = NULL;
+  init_declspec(&d->declspec, NULL);
   d->func_type = NULL;
   d->bits = NULL;
   return d;
@@ -1813,7 +1886,15 @@ static declarator_t *make_declarator(var_t *var)
 
 static type_t *make_safearray(type_t *type)
 {
-  return type_new_array(NULL, type_new_alias(type, "SAFEARRAY"), TRUE, 0,
+  decl_spec_t aliasee_ds;
+  decl_spec_t element_ds;
+
+  init_declspec(&element_ds,
+    type_new_alias(
+      init_declspec(&aliasee_ds, type),
+      "SAFEARRAY"));
+
+  return type_new_array(NULL, &element_ds, TRUE, 0,
                         NULL, NULL, FC_RP);
 }
 
@@ -1903,15 +1984,16 @@ type_t *reg_type(type_t *type, const char *name, struct namespace *namespace, in
   nt->t = t;
   nt->next = namespace->type_hash[hash];
   namespace->type_hash[hash] = nt;
-  if ((t == tsSTRUCT || t == tsUNION))
+  if ((t == tsSTRUCT || t == tsUNION || t == tsENUM))
     fix_incomplete_types(type);
   return type;
 }
 
 static int is_incomplete(const type_t *t)
 {
-  return !t->defined &&
-    (type_get_type_detect_alias(t) == TYPE_STRUCT ||
+  return !type_is_defined(t) &&
+    (type_get_type_detect_alias(t) == TYPE_ENUM ||
+     type_get_type_detect_alias(t) == TYPE_STRUCT ||
      type_get_type_detect_alias(t) == TYPE_UNION ||
      type_get_type_detect_alias(t) == TYPE_ENCAPSULATED_UNION);
 }
@@ -1919,19 +2001,16 @@ static int is_incomplete(const type_t *t)
 void add_incomplete(type_t *t)
 {
   struct typenode *tn = xmalloc(sizeof *tn);
+  assert(is_incomplete(t));
   tn->type = t;
   list_add_tail(&incomplete_types, &tn->entry);
 }
 
 static void fix_type(type_t *t)
 {
-  if (type_is_alias(t) && is_incomplete(t)) {
-    type_t *ot = type_alias_get_aliasee(t);
-    fix_type(ot);
-    if (type_get_type_detect_alias(ot) == TYPE_STRUCT ||
-        type_get_type_detect_alias(ot) == TYPE_UNION ||
-        type_get_type_detect_alias(ot) == TYPE_ENCAPSULATED_UNION)
-      t->details.structure = ot->details.structure;
+  if (type_is_alias(t) && is_incomplete(t)) 
+  {
+    type_t *ot = type_alias_get_aliasee_type(t);
     t->defined = ot->defined;
   }
 }
@@ -1955,7 +2034,7 @@ static void fix_incomplete_types(type_t *complete_type)
   {
     if (type_is_equal(complete_type, tn->type))
     {
-      tn->type->details.structure = complete_type->details.structure;
+      tn->type->details = complete_type->details;
       list_remove(&tn->entry);
       free(tn);
     }
@@ -1979,7 +2058,13 @@ static type_t *reg_typedefs(decl_spec_t *decl_spec, declarator_list_t *decls, at
       type_get_type_detect_alias(type) == TYPE_ENCAPSULATED_UNION)
   {
     if (!type->name)
+    {
       type->name = gen_name();
+      /* the generated name will be used and this typedef excluded from the
+       * built typelib unless the typedef has the 'public' attribute, so add it here */
+      if (do_typelib && !is_attr(attrs, ATTR_PUBLIC))
+        attrs = append_attr(attrs, make_attr(ATTR_PUBLIC));
+    }
 
     /* replace existing attributes when generating a typelib */
     if (do_typelib)
@@ -2010,7 +2095,7 @@ static type_t *reg_typedefs(decl_spec_t *decl_spec, declarator_list_t *decls, at
                     cur->loc_info.line_number);
 
       name = declare_var(attrs, decl_spec, decl, 0);
-      cur = type_new_alias(name->type, name->name);
+      cur = type_new_alias(&name->declspec, name->name);
       cur->attrs = attrs;
 
       if (is_incomplete(cur))
@@ -2178,7 +2263,6 @@ struct allowed_attr allowed_attr[] =
     /* ATTR_CASE */                { 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "case" },
     /* ATTR_CODE */                { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "code" },
     /* ATTR_COMMSTATUS */          { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "comm_status" },
-    /* ATTR_CONST */               { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "const" },
     /* ATTR_CONTEXTHANDLE */       { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "context_handle" },
     /* ATTR_CONTROL */             { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, "control" },
     /* ATTR_DECODE */              { 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "decode" },
@@ -2213,7 +2297,6 @@ struct allowed_attr allowed_attr[] =
     /* ATTR_IMMEDIATEBIND */       { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "immediatebind" },
     /* ATTR_IMPLICIT_HANDLE */     { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "implicit_handle" },
     /* ATTR_IN */                  { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "in" },
-    /* ATTR_INLINE */              { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inline" },
     /* ATTR_INPUTSYNC */           { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "inputsync" },
     /* ATTR_LENGTHIS */            { 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, "length_is" },
     /* ATTR_LIBLCID */             { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, "lcid" },
@@ -2285,10 +2368,10 @@ static attr_list_t *check_iface_attrs(const char *name, attr_list_t *attrs)
     if (attr->type == ATTR_IMPLICIT_HANDLE)
     {
         const var_t *var = attr->u.pval;
-        if (type_get_type( var->type) == TYPE_BASIC &&
-            type_basic_get_type( var->type ) == TYPE_BASIC_HANDLE)
+        if (type_get_type( var->declspec.type) == TYPE_BASIC &&
+            type_basic_get_type( var->declspec.type ) == TYPE_BASIC_HANDLE)
             continue;
-        if (is_aliaschain_attr( var->type, ATTR_HANDLE ))
+        if (is_aliaschain_attr( var->declspec.type, ATTR_HANDLE ))
             continue;
       error_loc("attribute %s requires a handle type in interface %s\n",
                 allowed_attr[attr->type].display_name, name);
@@ -2493,7 +2576,7 @@ static int is_ptr_guid_type(const type_t *type)
 
     /* second, make sure it is a pointer to something of size sizeof(GUID),
      * i.e. 16 bytes */
-    return (type_memsize(type_pointer_get_ref(type)) == 16);
+    return (type_memsize(type_pointer_get_ref_type(type)) == 16);
 }
 
 static void check_conformance_expr_list(const char *attr_name, const var_t *arg, const type_t *container_type, expr_list_t *expr_list)
@@ -2520,7 +2603,7 @@ static void check_remoting_fields(const var_t *var, type_t *type);
 static void check_field_common(const type_t *container_type,
                                const char *container_name, const var_t *arg)
 {
-    type_t *type = arg->type;
+    type_t *type = arg->declspec.type;
     int more_to_do;
     const char *container_type_name;
     const char *var_type;
@@ -2550,7 +2633,7 @@ static void check_field_common(const type_t *container_type,
     }
 
     if (is_attr(arg->attrs, ATTR_LENGTHIS) &&
-        (is_attr(arg->attrs, ATTR_STRING) || is_aliaschain_attr(arg->type, ATTR_STRING)))
+        (is_attr(arg->attrs, ATTR_STRING) || is_aliaschain_attr(arg->declspec.type, ATTR_STRING)))
         error_loc_info(&arg->loc_info,
                        "string and length_is specified for argument %s are mutually exclusive attributes\n",
                        arg->name);
@@ -2647,23 +2730,28 @@ static void check_field_common(const type_t *container_type,
         {
             const type_t *t = type;
             while (is_ptr(t))
-                t = type_pointer_get_ref(t);
+                t = type_pointer_get_ref_type(t);
             if (is_aliaschain_attr(t, ATTR_RANGE))
                 warning_loc_info(&arg->loc_info, "%s: range not verified for a string of ranged types\n", arg->name);
             break;
         }
         case TGT_POINTER:
-            type = type_pointer_get_ref(type);
+            type = type_pointer_get_ref_type(type);
             more_to_do = TRUE;
             break;
         case TGT_ARRAY:
-            type = type_array_get_element(type);
+            type = type_array_get_element_type(type);
             more_to_do = TRUE;
             break;
+        case TGT_ENUM:
+            type = type_get_real_type(type);
+            if(!type_is_complete(type))
+            {
+                error_loc_info(&arg->loc_info, "undefined type declaration enum %s\n", type->name);
+            }
         case TGT_USER_TYPE:
         case TGT_IFACE_POINTER:
         case TGT_BASIC:
-        case TGT_ENUM:
         case TGT_RANGE:
             /* nothing to do */
             break;
@@ -2688,13 +2776,18 @@ static void check_remoting_fields(const var_t *var, type_t *type)
         if (type_is_complete(type))
             fields = type_struct_get_fields(type);
         else
-            error_loc_info(&var->loc_info, "undefined type declaration %s\n", type->name);
+            error_loc_info(&var->loc_info, "undefined type declaration struct %s\n", type->name);
     }
     else if (type_get_type(type) == TYPE_UNION || type_get_type(type) == TYPE_ENCAPSULATED_UNION)
-        fields = type_union_get_cases(type);
+    {
+    	if (type_is_complete(type))
+            fields = type_union_get_cases(type);
+        else
+            error_loc_info(&var->loc_info, "undefined type declaration union %s\n", type->name);
+    }
 
     if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
-        if (field->type) check_field_common(type, type->name, field);
+        if (field->declspec.type) check_field_common(type, type->name, field);
 }
 
 /* checks that arguments for a function make sense for marshalling and unmarshalling */
@@ -2703,9 +2796,10 @@ static void check_remoting_args(const var_t *func)
     const char *funcname = func->name;
     const var_t *arg;
 
-    if (func->type->details.function->args) LIST_FOR_EACH_ENTRY( arg, func->type->details.function->args, const var_t, entry )
+    assert(type_get_type_detect_alias(func->declspec.type) == TYPE_FUNCTION);
+    if (func->declspec.type->details.function->args) LIST_FOR_EACH_ENTRY( arg, func->declspec.type->details.function->args, const var_t, entry )
     {
-        const type_t *type = arg->type;
+        const type_t *type = arg->declspec.type;
 
         /* check that [out] parameters have enough pointer levels */
         if (is_attr(arg->attrs, ATTR_OUT))
@@ -2745,16 +2839,16 @@ static void check_remoting_args(const var_t *func)
             }
         }
 
-        check_field_common(func->type, funcname, arg);
+        check_field_common(func->declspec.type, funcname, arg);
     }
 
-    if (type_get_type(type_function_get_rettype(func->type)) != TYPE_VOID)
+    if (type_get_type(type_function_get_rettype(func->declspec.type)) != TYPE_VOID)
     {
         var_t var;
         var = *func;
-        var.type = type_function_get_rettype(func->type);
+        var.declspec.type = type_function_get_rettype(func->declspec.type);
         var.name = xstrdup("return value");
-        check_field_common(func->type, funcname, &var);
+        check_field_common(func->declspec.type, funcname, &var);
         free(var.name);
     }
 }
@@ -2771,8 +2865,8 @@ static void add_explicit_handle_if_necessary(const type_t *iface, var_t *func)
          * function */
         var_t *idl_handle = make_var(xstrdup("IDL_handle"));
         idl_handle->attrs = append_attr(NULL, make_attr(ATTR_IN));
-        idl_handle->type = find_type_or_error("handle_t", 0);
-        type_function_add_head_arg(func->type, idl_handle);
+        idl_handle->declspec.type = find_type_or_error("handle_t", 0);
+        type_function_add_head_arg(func->declspec.type, idl_handle);
     }
 }
 
@@ -2837,6 +2931,7 @@ static void check_async_uuid(type_t *iface)
     type_t *async_iface;
     type_t *inherit;
 
+    assert(type_get_type_detect_alias(iface) == TYPE_INTERFACE);
     if (!is_attr(iface->attrs, ATTR_ASYNCUUID)) return;
 
     inherit = iface->details.iface->inherit;
@@ -2853,7 +2948,8 @@ static void check_async_uuid(type_t *iface)
         var_t *begin_func, *finish_func, *func = stmt->u.var, *arg;
         var_list_t *begin_args = NULL, *finish_args = NULL, *args;
 
-        args = func->type->details.function->args;
+        assert(type_get_type_detect_alias(func->declspec.type) == TYPE_FUNCTION);
+        args = func->declspec.type->details.function->args;
         if (args) LIST_FOR_EACH_ENTRY(arg, args, var_t, entry)
         {
             if (is_attr(arg->attrs, ATTR_IN) || !is_attr(arg->attrs, ATTR_OUT))
@@ -2863,15 +2959,15 @@ static void check_async_uuid(type_t *iface)
         }
 
         begin_func = copy_var(func, concat_str("Begin_", func->name), NULL);
-        begin_func->type = type_new_function(begin_args);
-        begin_func->type->attrs = func->attrs;
-        begin_func->type->details.function->retval = func->type->details.function->retval;
+        begin_func->declspec.type = type_new_function(begin_args);
+        begin_func->declspec.type->attrs = func->attrs;
+        begin_func->declspec.type->details.function->retval = func->declspec.type->details.function->retval;
         stmts = append_statement(stmts, make_statement_declaration(begin_func));
 
         finish_func = copy_var(func, concat_str("Finish_", func->name), NULL);
-        finish_func->type = type_new_function(finish_args);
-        finish_func->type->attrs = func->attrs;
-        finish_func->type->details.function->retval = func->type->details.function->retval;
+        finish_func->declspec.type = type_new_function(finish_args);
+        finish_func->declspec.type->attrs = func->attrs;
+        finish_func->declspec.type->details.function->retval = func->declspec.type->details.function->retval;
         stmts = append_statement(stmts, make_statement_declaration(finish_func));
     }
 
@@ -2911,6 +3007,7 @@ static void check_statements(const statement_list_t *stmts, int is_inside_librar
 static void check_all_user_types(const statement_list_t *stmts)
 {
   const statement_t *stmt;
+  const var_t *v;
 
   if (stmts) LIST_FOR_EACH_ENTRY(stmt, stmts, const statement_t, entry)
   {
@@ -2922,7 +3019,11 @@ static void check_all_user_types(const statement_list_t *stmts)
       const statement_t *stmt_func;
       STATEMENTS_FOR_EACH_FUNC(stmt_func, type_iface_get_stmts(stmt->u.type)) {
         const var_t *func = stmt_func->u.var;
-        check_for_additional_prototype_types(func->type->details.function->args);
+        assert(type_get_type_detect_alias(func->declspec.type) == TYPE_FUNCTION);
+        if (func->declspec.type->details.function->args)
+          LIST_FOR_EACH_ENTRY( v, func->declspec.type->details.function->args, const var_t, entry )
+            check_for_additional_prototype_types(v->declspec.type);
+        check_for_additional_prototype_types(type_function_get_rettype(func->declspec.type));
       }
     }
   }
@@ -2956,6 +3057,10 @@ static statement_t *make_statement_type_decl(type_t *type)
 {
     statement_t *stmt = make_statement(STMT_TYPE);
     stmt->u.type = type;
+    if (type_is_defined(type))
+    {
+        stmt->declonly = FALSE;
+    }
     return stmt;
 }
 
@@ -2970,16 +3075,16 @@ static statement_t *make_statement_declaration(var_t *var)
 {
     statement_t *stmt = make_statement(STMT_DECLARATION);
     stmt->u.var = var;
-    if (var->stgclass == STG_EXTERN && var->eval)
+    if (var->declspec.stgclass == STG_EXTERN && var->eval)
         warning("'%s' initialised and declared extern\n", var->name);
     if (is_const_decl(var))
     {
         if (var->eval)
             reg_const(var);
     }
-    else if (type_get_type(var->type) == TYPE_FUNCTION)
+    else if (type_get_type(var->declspec.type) == TYPE_FUNCTION)
         check_function_attrs(var->name, var->attrs);
-    else if (var->stgclass == STG_NONE || var->stgclass == STG_REGISTER)
+    else if (var->declspec.stgclass == STG_NONE || var->declspec.stgclass == STG_REGISTER)
         error_loc("instantiation of data is illegal\n");
     return stmt;
 }
@@ -3031,6 +3136,7 @@ static statement_t *make_statement_typedef(declarator_list_t *decls)
     declarator_t *decl, *next;
     statement_t *stmt;
     type_list_t **type_list;
+    int defined = TRUE;
 
     if (!decls) return NULL;
 
@@ -3042,6 +3148,18 @@ static statement_t *make_statement_typedef(declarator_list_t *decls)
     {
         var_t *var = decl->var;
         type_t *type = find_type_or_error(var->name, 0);
+
+        /* ensure that all of the types in this typedef statement have been defined
+         * before setting its declonly flag */
+        if (type_is_pointerish(type))
+        {
+            defined = defined & type_is_defined(type_get_pointer_chain_tail(type));
+        }
+        else
+        {
+            defined = defined & type_is_defined(type_get_real_type(type));
+        }
+
         *type_list = xmalloc(sizeof(type_list_t));
         (*type_list)->type = type;
         (*type_list)->next = NULL;
@@ -3051,6 +3169,7 @@ static statement_t *make_statement_typedef(declarator_list_t *decls)
         free(var);
     }
 
+    stmt->declonly = !defined;
     return stmt;
 }
 
@@ -3091,7 +3210,7 @@ void init_loc_info(loc_info_t *i)
 
 static void check_def(const type_t *t)
 {
-    if (t->defined)
+    if (type_is_defined(t))
         error_loc("%s: redefinition error; original definition was at %s:%d\n",
                   t->name, t->loc_info.input_name, t->loc_info.line_number);
 }
diff --git a/mingw-w64-tools/widl/src/parser.yy.c b/mingw-w64-tools/widl/src/parser.yy.c
index 2aaf3c27..0482aa7e 100644
--- a/mingw-w64-tools/widl/src/parser.yy.c
+++ b/mingw-w64-tools/widl/src/parser.yy.c
@@ -1,6 +1,6 @@
-#line 1 "parser.yy.c"
+#line 2 "parser.yy.c"
 
-#line 3 "parser.yy.c"
+#line 4 "parser.yy.c"
 
 #define  YY_INT_ALIGNED short int
 
@@ -1041,13 +1041,13 @@ UUID *parse_uuid(const char *u)
   return uuid;
 }
 
-#line 1044 "parser.yy.c"
+#line 1045 "parser.yy.c"
 /*
  **************************************************************************
  * The flexer starts here
  **************************************************************************
  */
-#line 1050 "parser.yy.c"
+#line 1051 "parser.yy.c"
 
 #define INITIAL 0
 #define QUOTE 1
@@ -1281,7 +1281,7 @@ YY_DECL
 	{
 #line 132 "parser.l"
 
-#line 1284 "parser.yy.c"
+#line 1285 "parser.yy.c"
 
 	while ( /*CONSTCOND*/1 )		/* loops until end-of-file is reached */
 		{
@@ -1616,7 +1616,7 @@ YY_RULE_SETUP
 #line 239 "parser.l"
 ECHO;
 	YY_BREAK
-#line 1619 "parser.yy.c"
+#line 1620 "parser.yy.c"
 
 	case YY_END_OF_BUFFER:
 		{
diff --git a/mingw-w64-tools/widl/src/proxy.c b/mingw-w64-tools/widl/src/proxy.c
index 87c27be9..36b552be 100644
--- a/mingw-w64-tools/widl/src/proxy.c
+++ b/mingw-w64-tools/widl/src/proxy.c
@@ -67,7 +67,7 @@ static void write_stubdesc(int expr_eval_routines)
   print_proxy( "1, /* -error bounds_check flag */\n");
   print_proxy( "0x%x, /* Ndr library version */\n", get_stub_mode() == MODE_Oif ? 0x50002 : 0x10001);
   print_proxy( "0,\n");
-  print_proxy( "0x50100a4, /* MIDL Version 5.1.164 */\n");
+  print_proxy( "0x50200ca, /* MIDL Version 5.2.202 */\n");
   print_proxy( "0,\n");
   print_proxy("%s,\n", list_empty(&user_type_list) ? "0" : "UserMarshalRoutines");
   print_proxy( "0,  /* notify & notify_flag routine table */\n");
@@ -105,15 +105,15 @@ static void clear_output_vars( const var_list_t *args )
   {
       if (is_attr(arg->attrs, ATTR_IN)) continue;
       if (!is_attr(arg->attrs, ATTR_OUT)) continue;
-      if (is_ptr(arg->type))
+      if (is_ptr(arg->declspec.type))
       {
-          if (type_get_type(type_pointer_get_ref(arg->type)) == TYPE_BASIC) continue;
-          if (type_get_type(type_pointer_get_ref(arg->type)) == TYPE_ENUM) continue;
+          if (type_get_type(type_pointer_get_ref_type(arg->declspec.type)) == TYPE_BASIC) continue;
+          if (type_get_type(type_pointer_get_ref_type(arg->declspec.type)) == TYPE_ENUM) continue;
       }
       print_proxy( "if (%s) MIDL_memset( %s, 0, ", arg->name, arg->name );
-      if (is_array(arg->type) && type_array_has_conformance(arg->type))
+      if (is_array(arg->declspec.type) && type_array_has_conformance(arg->declspec.type))
       {
-          write_expr( proxy, type_array_get_conformance(arg->type), 1, 1, NULL, NULL, "" );
+          write_expr( proxy, type_array_get_conformance(arg->declspec.type), 1, 1, NULL, NULL, "" );
           fprintf( proxy, " * " );
       }
       fprintf( proxy, "sizeof( *%s ));\n", arg->name );
@@ -147,7 +147,7 @@ static int need_delegation_indirect(const type_t *iface)
 static void free_variable( const var_t *arg, const char *local_var_prefix )
 {
   unsigned int type_offset = arg->typestring_offset;
-  type_t *type = arg->type;
+  type_t *type = arg->declspec.type;
 
   write_parameter_conf_or_var_exprs(proxy, indent, local_var_prefix, PHASE_FREE, arg, FALSE);
 
@@ -191,18 +191,18 @@ static void proxy_free_variables( var_list_t *args, const char *local_var_prefix
 static void gen_proxy(type_t *iface, const var_t *func, int idx,
                       unsigned int proc_offset)
 {
-  var_t *retval = type_function_get_retval(func->type);
-  int has_ret = !is_void(retval->type);
+  var_t *retval = type_function_get_retval(func->declspec.type);
+  int has_ret = !is_void(retval->declspec.type);
   int has_full_pointer = is_full_pointer_function(func);
-  const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV);
-  const var_list_t *args = type_get_function_args(func->type);
+  const char *callconv = get_attrp(func->declspec.type->attrs, ATTR_CALLCONV);
+  const var_list_t *args = type_function_get_args(func->declspec.type);
   if (!callconv) callconv = "STDMETHODCALLTYPE";
 
   indent = 0;
   if (is_interpreted_func( iface, func ))
   {
       if (get_stub_mode() == MODE_Oif && !is_callas( func->attrs )) return;
-      write_type_decl_left(proxy, retval->type);
+      write_declspec_decl_left(proxy, &retval->declspec);
       print_proxy( " %s %s_%s_Proxy(\n", callconv, iface->name, get_name(func));
       write_args(proxy, args, iface->name, 1, TRUE);
       print_proxy( ")\n");
@@ -219,7 +219,7 @@ static void gen_proxy(type_t *iface, const var_t *func, int idx,
   print_proxy( "}\n");
   print_proxy( "\n");
 
-  write_type_decl_left(proxy, retval->type);
+  write_declspec_decl_left(proxy, &retval->declspec);
   print_proxy( " %s %s_%s_Proxy(\n", callconv, iface->name, get_name(func));
   write_args(proxy, args, iface->name, 1, TRUE);
   print_proxy( ")\n");
@@ -229,12 +229,12 @@ static void gen_proxy(type_t *iface, const var_t *func, int idx,
   /* local variables */
   if (has_ret) {
     print_proxy( "%s", "" );
-    write_type_decl(proxy, retval->type, retval->name);
+    write_declspec_decl(proxy, &retval->declspec, retval->name);
     fprintf( proxy, ";\n" );
   }
   print_proxy( "RPC_MESSAGE _RpcMessage;\n" );
   if (has_ret) {
-    if (decl_indirect(retval->type))
+    if (decl_indirect(retval->declspec.type))
         print_proxy("void *_p_%s = &%s;\n", retval->name, retval->name);
   }
   print_proxy( "\n");
@@ -246,7 +246,7 @@ static void gen_proxy(type_t *iface, const var_t *func, int idx,
     write_full_pointer_init(proxy, indent, func, FALSE);
 
   /* FIXME: trace */
-  clear_output_vars( type_get_function_args(func->type) );
+  clear_output_vars( type_function_get_args(func->declspec.type) );
 
   print_proxy( "RpcTryExcept\n" );
   print_proxy( "{\n" );
@@ -279,9 +279,9 @@ static void gen_proxy(type_t *iface, const var_t *func, int idx,
 
   if (has_ret)
   {
-      if (decl_indirect(retval->type))
+      if (decl_indirect(retval->declspec.type))
           print_proxy("MIDL_memset(&%s, 0, sizeof(%s));\n", retval->name, retval->name);
-      else if (is_ptr(retval->type) || is_array(retval->type))
+      else if (is_ptr(retval->declspec.type) || is_array(retval->declspec.type))
           print_proxy("%s = 0;\n", retval->name);
       write_remoting_arguments(proxy, indent, func, "", PASS_RETURN, PHASE_UNMARSHAL);
   }
@@ -301,7 +301,7 @@ static void gen_proxy(type_t *iface, const var_t *func, int idx,
   print_proxy( "{\n" );
   if (has_ret) {
     indent++;
-    proxy_free_variables( type_get_function_args(func->type), "" );
+    proxy_free_variables( type_function_get_args(func->declspec.type), "" );
     print_proxy( "_RetVal = NdrProxyErrorHandler(RpcExceptionCode());\n" );
     indent--;
   }
@@ -320,7 +320,7 @@ static void gen_stub(type_t *iface, const var_t *func, const char *cas,
                      unsigned int proc_offset)
 {
   const var_t *arg;
-  int has_ret = !is_void(type_function_get_rettype(func->type));
+  int has_ret = !is_void(type_function_get_rettype(func->declspec.type));
   int has_full_pointer = is_full_pointer_function(func);
 
   if (is_interpreted_func( iface, func )) return;
@@ -389,10 +389,10 @@ static void gen_stub(type_t *iface, const var_t *func, const char *cas,
   else fprintf(proxy, "__frame->_This->lpVtbl->%s", get_name(func));
   fprintf(proxy, "(__frame->_This");
 
-  if (type_get_function_args(func->type))
+  if (type_function_get_args(func->declspec.type))
   {
-      LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), const var_t, entry )
-          fprintf(proxy, ", %s__frame->%s", is_array(arg->type) && !type_array_is_decl_as_ptr(arg->type) ? "*" :"" , arg->name);
+      LIST_FOR_EACH_ENTRY( arg, type_function_get_args(func->declspec.type), const var_t, entry )
+          fprintf(proxy, ", %s__frame->%s", is_array(arg->declspec.type) && !type_array_is_decl_as_ptr(arg->declspec.type) ? "*" :"" , arg->name);
   }
   fprintf(proxy, ");\n");
   fprintf(proxy, "\n");
@@ -401,7 +401,7 @@ static void gen_stub(type_t *iface, const var_t *func, const char *cas,
 
   write_remoting_arguments(proxy, indent, func, "__frame->", PASS_OUT, PHASE_BUFFERSIZE);
 
-  if (!is_void(type_function_get_rettype(func->type)))
+  if (!is_void(type_function_get_rettype(func->declspec.type)))
     write_remoting_arguments(proxy, indent, func, "__frame->", PASS_RETURN, PHASE_BUFFERSIZE);
 
   print_proxy("NdrStubGetBuffer(This, _pRpcChannelBuffer, &__frame->_StubMsg);\n");
@@ -410,7 +410,7 @@ static void gen_stub(type_t *iface, const var_t *func, const char *cas,
   fprintf(proxy, "\n");
 
   /* marshall the return value */
-  if (!is_void(type_function_get_rettype(func->type)))
+  if (!is_void(type_function_get_rettype(func->declspec.type)))
     write_remoting_arguments(proxy, indent, func, "__frame->", PASS_RETURN, PHASE_MARSHAL);
 
   indent--;
@@ -432,16 +432,16 @@ static void gen_stub(type_t *iface, const var_t *func, const char *cas,
 
 static void gen_stub_thunk( type_t *iface, const var_t *func, unsigned int proc_offset )
 {
-    int has_ret = !is_void( type_function_get_rettype( func->type ));
+    int has_ret = !is_void( type_function_get_rettype( func->declspec.type ));
     const var_t *arg, *callas = is_callas( func->attrs );
-    const var_list_t *args = type_get_function_args( func->type );
+    const var_list_t *args = type_function_get_args( func->declspec.type );
 
     indent = 0;
     print_proxy( "void __RPC_API %s_%s_Thunk( PMIDL_STUB_MESSAGE pStubMsg )\n",
                  iface->name, get_name(func) );
     print_proxy( "{\n");
     indent++;
-    write_func_param_struct( proxy, iface, func->type,
+    write_func_param_struct( proxy, iface, func->declspec.type,
                              "*pParamStruct = (struct _PARAM_STRUCT *)pStubMsg->StackTop", has_ret );
     print_proxy( "%s%s_%s_Stub( pParamStruct->This",
                  has_ret ? "pParamStruct->_RetVal = " : "", iface->name, callas->name );
@@ -526,6 +526,7 @@ static int write_proxy_methods(type_t *iface, int skip)
       if (skip || (is_local(func->attrs) && !get_callas_source(iface, func)))
           print_proxy( "0,  /* %s::%s */\n", iface->name, get_name(func));
       else if (is_interpreted_func( iface, func ) &&
+               get_stub_mode() == MODE_Oif &&
                !is_local( func->attrs ) &&
                type_iface_get_inherit(iface))
           print_proxy( "(void *)-1,  /* %s::%s */\n", iface->name, get_name(func));
@@ -613,14 +614,14 @@ static void write_proxy(type_t *iface, unsigned int *proc_offset)
     if (!is_local(func->attrs)) {
       const var_t *cas = is_callas(func->attrs);
       const char *cname = cas ? cas->name : NULL;
-      int idx = func->type->details.function->idx;
+      int idx = type_get_details(func->declspec.type)->function->idx;
       if (cname) {
           const statement_t *stmt2;
           STATEMENTS_FOR_EACH_FUNC(stmt2, type_iface_get_stmts(iface)) {
               const var_t *m = stmt2->u.var;
               if (!strcmp(m->name, cname))
               {
-                  idx = m->type->details.function->idx;
+                  idx = type_get_details(m->declspec.type)->function->idx;
                   break;
               }
           }
@@ -738,7 +739,7 @@ static void write_proxy(type_t *iface, unsigned int *proc_offset)
   print_proxy( "{\n");
   indent++;
   print_proxy( "%s_%s\n",
-               iface->details.iface->async_iface == iface ? "CStdAsyncStubBuffer" : "CStdStubBuffer",
+               type_get_details(iface)->iface->async_iface == iface ? "CStdAsyncStubBuffer" : "CStdStubBuffer",
                need_delegation_indirect(iface) ? "DELEGATING_METHODS" : "METHODS");
   indent--;
   print_proxy( "}\n");
@@ -839,8 +840,8 @@ static void write_proxy_stmts(const statement_list_t *stmts, unsigned int *proc_
       if (need_proxy(iface))
       {
         write_proxy(iface, proc_offset);
-        if (iface->details.iface->async_iface)
-          write_proxy(iface->details.iface->async_iface, proc_offset);
+        if (type_get_details(iface)->iface->async_iface)
+          write_proxy(type_get_details(iface)->iface->async_iface, proc_offset);
       }
     }
   }
@@ -869,9 +870,9 @@ static void build_iface_list( const statement_list_t *stmts, type_t **ifaces[],
             {
                 *ifaces = xrealloc( *ifaces, (*count + 1) * sizeof(**ifaces) );
                 (*ifaces)[(*count)++] = iface;
-                if (iface->details.iface->async_iface)
+                if (type_get_details(iface)->iface->async_iface)
                 {
-                    iface = iface->details.iface->async_iface;
+                    iface = type_get_details(iface)->iface->async_iface;
                     *ifaces = xrealloc( *ifaces, (*count + 1) * sizeof(**ifaces) );
                     (*ifaces)[(*count)++] = iface;
                 }
@@ -942,7 +943,7 @@ static void write_proxy_routines(const statement_list_t *stmts)
   write_stubdesc(expr_eval_routines);
 
   print_proxy( "#if !defined(__RPC_WIN%u__)\n", pointer_size == 8 ? 64 : 32);
-  print_proxy( "#error Currently only Wine and WIN32 are supported.\n");
+  print_proxy( "#error Invalid build platform for this proxy.\n");
   print_proxy( "#endif\n");
   print_proxy( "\n");
   write_procformatstring(proxy, stmts, need_proxy);
@@ -1011,7 +1012,7 @@ static void write_proxy_routines(const statement_list_t *stmts)
   table_version = get_stub_mode() == MODE_Oif ? 2 : 1;
   for (i = 0; i < count; i++)
   {
-      if (interfaces[i]->details.iface->async_iface != interfaces[i]) continue;
+      if (type_get_details(interfaces[i])->iface->async_iface != interfaces[i]) continue;
       if (table_version != 6)
       {
           fprintf(proxy, "static const IID *_AsyncInterfaceTable[] =\n");
@@ -1053,26 +1054,6 @@ void write_proxies(const statement_list_t *stmts)
   init_proxy(stmts);
   if(!proxy) return;
 
-  if (do_win32 && do_win64)
-  {
-      fprintf(proxy, "\n#ifndef _WIN64\n\n");
-      pointer_size = 4;
-      write_proxy_routines( stmts );
-      fprintf(proxy, "\n#else /* _WIN64 */\n\n");
-      pointer_size = 8;
-      write_proxy_routines( stmts );
-      fprintf(proxy, "\n#endif /* _WIN64 */\n");
-  }
-  else if (do_win32)
-  {
-      pointer_size = 4;
-      write_proxy_routines( stmts );
-  }
-  else if (do_win64)
-  {
-      pointer_size = 8;
-      write_proxy_routines( stmts );
-  }
-
+  write_proxy_routines( stmts );
   fclose(proxy);
 }
diff --git a/mingw-w64-tools/widl/src/register.c b/mingw-w64-tools/widl/src/register.c
index 210fb747..1c369e7c 100644
--- a/mingw-w64-tools/widl/src/register.c
+++ b/mingw-w64-tools/widl/src/register.c
@@ -325,7 +325,7 @@ void output_typelib_regscript( const typelib_t *typelib )
         sprintf(resname, "%s\\%d", typelib_name, expr->cval);
     }
     put_str( indent, "'%x' { %s = s '%%MODULE%%%s' }\n",
-             lcid_expr ? lcid_expr->cval : 0, typelib_kind == SYS_WIN64 ? "win64" : "win32", id_part );
+             lcid_expr ? lcid_expr->cval : 0, pointer_size == 8 ? "win64" : "win32", id_part );
     put_str( indent, "FLAGS = s '%u'\n", flags );
     put_str( --indent, "}\n" );
     put_str( --indent, "}\n" );
diff --git a/mingw-w64-tools/widl/src/server.c b/mingw-w64-tools/widl/src/server.c
index 783ff900..dbed870a 100644
--- a/mingw-w64-tools/widl/src/server.c
+++ b/mingw-w64-tools/widl/src/server.c
@@ -55,6 +55,8 @@ static void write_function_stub(const type_t *iface, const var_t *func, unsigned
     unsigned char explicit_fc, implicit_fc;
     int has_full_pointer = is_full_pointer_function(func);
     const var_t *handle_var = get_func_handle_var( iface, func, &explicit_fc, &implicit_fc );
+    const decl_spec_t *ret_declspec = type_function_get_retdeclspec(func->declspec.type);
+    type_t *ret_type = ret_declspec->type;
 
     if (is_interpreted_func( iface, func )) return;
 
@@ -75,7 +77,7 @@ static void write_function_stub(const type_t *iface, const var_t *func, unsigned
     indent++;
     write_remoting_arguments(server, indent, func, "__frame->", PASS_OUT, PHASE_FREE);
 
-    if (!is_void(type_function_get_rettype(func->type)))
+    if (!is_void(ret_type))
         write_remoting_arguments(server, indent, func, "__frame->", PASS_RETURN, PHASE_FREE);
 
     if (has_full_pointer)
@@ -120,7 +122,7 @@ static void write_function_stub(const type_t *iface, const var_t *func, unsigned
     if (has_full_pointer)
         write_full_pointer_init(server, indent, func, TRUE);
 
-    if (type_get_function_args(func->type))
+    if (type_function_get_args(func->declspec.type))
     {
         print_server("if ((_pRpcMessage->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)\n");
         indent++;
@@ -154,35 +156,42 @@ static void write_function_stub(const type_t *iface, const var_t *func, unsigned
     assign_stub_out_args(server, indent, func, "__frame->");
 
     /* Call the real server function */
-    print_server("%s%s%s",
-                 is_void(type_function_get_rettype(func->type)) ? "" : "__frame->_RetVal = ",
-                 prefix_server, get_name(func));
+    if (is_context_handle(ret_type))
+    {
+        print_server("__frame->_RetVal = NDRSContextUnmarshall((char*)0, _pRpcMessage->DataRepresentation);\n");
+        print_server("*((");
+        write_declspec_decl(server, ret_declspec, NULL);
+        fprintf(server, "*)NDRSContextValue(__frame->_RetVal)) = ");
+    }
+    else
+        print_server("%s", is_void(ret_type) ? "" : "__frame->_RetVal = ");
+    fprintf(server, "%s%s", prefix_server, get_name(func));
 
-    if (type_get_function_args(func->type))
+    if (type_function_get_args(func->declspec.type))
     {
         int first_arg = 1;
 
         fprintf(server, "(\n");
         indent++;
-        LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
+        LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), const var_t, entry )
         {
             if (first_arg)
                 first_arg = 0;
             else
                 fprintf(server, ",\n");
-            if (is_context_handle(var->type))
+            if (is_context_handle(var->declspec.type))
             {
                 /* if the context_handle attribute appears in the chain of types
                  * without pointers being followed, then the context handle must
                  * be direct, otherwise it is a pointer */
-                const char *ch_ptr = is_aliaschain_attr(var->type, ATTR_CONTEXTHANDLE) ? "*" : "";
+                const char *ch_ptr = is_aliaschain_attr(var->declspec.type, ATTR_CONTEXTHANDLE) ? "*" : "";
                 print_server("(");
-                write_type_decl_left(server, var->type);
+                write_declspec_decl_left(server, &var->declspec);
                 fprintf(server, ")%sNDRSContextValue(__frame->%s)", ch_ptr, var->name);
             }
             else
             {
-                print_server("%s__frame->%s", is_array(var->type) && !type_array_is_decl_as_ptr(var->type) ? "*" : "", var->name);
+                print_server("%s__frame->%s", is_array(var->declspec.type) && !type_array_is_decl_as_ptr(var->declspec.type) ? "*" : "", var->name);
             }
         }
         fprintf(server, ");\n");
@@ -197,7 +206,7 @@ static void write_function_stub(const type_t *iface, const var_t *func, unsigned
     {
         write_remoting_arguments(server, indent, func, "__frame->", PASS_OUT, PHASE_BUFFERSIZE);
 
-        if (!is_void(type_function_get_rettype(func->type)))
+        if (!is_void(ret_type))
             write_remoting_arguments(server, indent, func, "__frame->", PASS_RETURN, PHASE_BUFFERSIZE);
 
         print_server("_pRpcMessage->BufferLength = __frame->_StubMsg.BufferLength;\n");
@@ -216,7 +225,7 @@ static void write_function_stub(const type_t *iface, const var_t *func, unsigned
     write_remoting_arguments(server, indent, func, "__frame->", PASS_OUT, PHASE_MARSHAL);
 
     /* marshall the return value */
-    if (!is_void(type_function_get_rettype(func->type)))
+    if (!is_void(ret_type))
         write_remoting_arguments(server, indent, func, "__frame->", PASS_RETURN, PHASE_MARSHAL);
 
     indent--;
@@ -378,7 +387,7 @@ static void write_stubdescriptor(type_t *iface, int expr_eval_routines)
     print_server("1, /* -error bounds_check flag */\n");
     print_server("0x%x, /* Ndr library version */\n", get_stub_mode() == MODE_Oif ? 0x50002 : 0x10001);
     print_server("0,\n");
-    print_server("0x50100a4, /* MIDL Version 5.1.164 */\n");
+    print_server("0x50200ca, /* MIDL Version 5.2.202 */\n");
     print_server("0,\n");
     print_server("%s,\n", list_empty(&user_type_list) ? "0" : "UserMarshalRoutines");
     print_server("0,  /* notify & notify_flag routine table */\n");
@@ -544,26 +553,6 @@ void write_server(const statement_list_t *stmts)
     if (!server)
         return;
 
-    if (do_win32 && do_win64)
-    {
-        fprintf(server, "#ifndef _WIN64\n\n");
-        pointer_size = 4;
-        write_server_routines( stmts );
-        fprintf(server, "\n#else /* _WIN64 */\n\n");
-        pointer_size = 8;
-        write_server_routines( stmts );
-        fprintf(server, "\n#endif /* _WIN64 */\n");
-    }
-    else if (do_win32)
-    {
-        pointer_size = 4;
-        write_server_routines( stmts );
-    }
-    else if (do_win64)
-    {
-        pointer_size = 8;
-        write_server_routines( stmts );
-    }
-
+    write_server_routines( stmts );
     fclose(server);
 }
diff --git a/mingw-w64-tools/widl/src/typegen.c b/mingw-w64-tools/widl/src/typegen.c
index 27ba60fc..eebb99f0 100644
--- a/mingw-w64-tools/widl/src/typegen.c
+++ b/mingw-w64-tools/widl/src/typegen.c
@@ -67,6 +67,7 @@ enum type_context
     TYPE_CONTEXT_PARAM,
     TYPE_CONTEXT_CONTAINER,
     TYPE_CONTEXT_CONTAINER_NO_POINTERS,
+    TYPE_CONTEXT_RETVAL,
 };
 
 /* parameter flags in Oif mode */
@@ -84,14 +85,14 @@ static const unsigned short IsSimpleRef = 0x0100;
 
 static unsigned int field_memsize(const type_t *type, unsigned int *offset);
 static unsigned int fields_memsize(const var_list_t *fields, unsigned int *align);
-static unsigned int write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
+static unsigned int write_array_tfs(FILE *file, const attr_list_t *attrs, const decl_spec_t *declspec,
                                     const char *name, unsigned int *typestring_offset);
-static unsigned int write_struct_tfs(FILE *file, type_t *type, const char *name, unsigned int *tfsoff);
-static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
+static unsigned int write_struct_tfs(FILE *file, const decl_spec_t *declspec, const char *name, unsigned int *tfsoff);
+static int write_embedded_types(FILE *file, const attr_list_t *attrs, const decl_spec_t *declspec,
                                 const char *name, int write_ptr, unsigned int *tfsoff);
 static const var_t *find_array_or_string_in_struct(const type_t *type);
 static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs,
-                                     type_t *type, enum type_context context,
+                                     const decl_spec_t *declspec, enum type_context context,
                                      const char *name, unsigned int *typestring_offset);
 static unsigned int get_required_buffer_size_type( const type_t *type, const char *name,
                                                    const attr_list_t *attrs, int toplevel_param,
@@ -196,7 +197,7 @@ static void *get_aliaschain_attrp(const type_t *type, enum attr_type attr)
         if (is_attr(t->attrs, attr))
             return get_attrp(t->attrs, attr);
         else if (type_is_alias(t))
-            t = type_alias_get_aliasee(t);
+            t = type_alias_get_aliasee_type(t);
         else return NULL;
     }
 }
@@ -266,7 +267,7 @@ unsigned char get_pointer_fc(const type_t *type, const attr_list_t *attrs, int t
     if (pointer_type)
         return pointer_type;
 
-    for (t = type; type_is_alias(t); t = type_alias_get_aliasee(t))
+    for (t = type; type_is_alias(t); t = type_alias_get_aliasee_type(t))
     {
         pointer_type = get_attrv(t->attrs, ATTR_POINTERTYPE);
         if (pointer_type)
@@ -287,7 +288,7 @@ static unsigned char get_pointer_fc_context( const type_t *type, const attr_list
     int pointer_fc = get_pointer_fc(type, attrs, context == TYPE_CONTEXT_TOPLEVELPARAM);
 
     if (pointer_fc == FC_UP && is_attr( attrs, ATTR_OUT ) &&
-        context == TYPE_CONTEXT_PARAM && is_object( current_iface ))
+        (context == TYPE_CONTEXT_PARAM || context == TYPE_CONTEXT_RETVAL) && is_object( current_iface ))
         pointer_fc = FC_OP;
 
     return pointer_fc;
@@ -315,7 +316,7 @@ static type_t *get_user_type(const type_t *t, const char **pname)
         }
 
         if (type_is_alias(t))
-            t = type_alias_get_aliasee(t);
+            t = type_alias_get_aliasee_type(t);
         else
             return NULL;
     }
@@ -350,10 +351,10 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att
             return TGT_RANGE;
         return TGT_ENUM;
     case TYPE_POINTER:
-        if (type_get_type(type_pointer_get_ref(type)) == TYPE_INTERFACE ||
-            (type_get_type(type_pointer_get_ref(type)) == TYPE_VOID && is_attr(attrs, ATTR_IIDIS)))
+        if (type_get_type(type_pointer_get_ref_type(type)) == TYPE_INTERFACE ||
+            (type_get_type(type_pointer_get_ref_type(type)) == TYPE_VOID && is_attr(attrs, ATTR_IIDIS)))
             return TGT_IFACE_POINTER;
-        else if (is_aliaschain_attr(type_pointer_get_ref(type), ATTR_CONTEXTHANDLE))
+        else if (is_aliaschain_attr(type_pointer_get_ref_type(type), ATTR_CONTEXTHANDLE))
             return TGT_CTXT_HANDLE_POINTER;
         else
             return TGT_POINTER;
@@ -378,13 +379,13 @@ enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *att
 
 static int cant_be_null(const var_t *v)
 {
-    switch (typegen_detect_type(v->type, v->attrs, TDT_IGNORE_STRINGS))
+    switch (typegen_detect_type(v->declspec.type, v->attrs, TDT_IGNORE_STRINGS))
     {
     case TGT_ARRAY:
-        if (!type_array_is_decl_as_ptr( v->type )) return 0;
+        if (!type_array_is_decl_as_ptr( v->declspec.type )) return 0;
         /* fall through */
     case TGT_POINTER:
-        return (get_pointer_fc(v->type, v->attrs, TRUE) == FC_RP);
+        return (get_pointer_fc(v->declspec.type, v->attrs, TRUE) == FC_RP);
     case TGT_CTXT_HANDLE_POINTER:
         return TRUE;
     default:
@@ -404,7 +405,7 @@ static int get_padding(const var_list_t *fields)
 
     LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry)
     {
-        type_t *ft = f->type;
+        type_t *ft = f->declspec.type;
         unsigned int align = 0;
         unsigned int size = type_memsize_and_alignment(ft, &align);
         align = clamp_align(align);
@@ -421,7 +422,7 @@ static unsigned int get_stack_size( const var_t *var, int *by_value )
     unsigned int stack_size;
     int by_val;
 
-    switch (typegen_detect_type( var->type, var->attrs, TDT_ALL_TYPES ))
+    switch (typegen_detect_type( var->declspec.type, var->attrs, TDT_ALL_TYPES ))
     {
     case TGT_BASIC:
     case TGT_ENUM:
@@ -429,7 +430,7 @@ static unsigned int get_stack_size( const var_t *var, int *by_value )
     case TGT_STRUCT:
     case TGT_UNION:
     case TGT_USER_TYPE:
-        stack_size = type_memsize( var->type );
+        stack_size = type_memsize( var->declspec.type );
         by_val = (pointer_size < 8 || stack_size <= pointer_size); /* FIXME: should be platform-specific */
         break;
     default:
@@ -442,23 +443,27 @@ static unsigned int get_stack_size( const var_t *var, int *by_value )
 }
 
 static unsigned char get_contexthandle_flags( const type_t *iface, const attr_list_t *attrs,
-                                              const type_t *type )
+                                              const type_t *type, int is_return )
 {
     unsigned char flags = 0;
+    int is_out;
 
     if (is_attr(iface->attrs, ATTR_STRICTCONTEXTHANDLE)) flags |= NDR_STRICT_CONTEXT_HANDLE;
 
     if (is_ptr(type) &&
         !is_attr( type->attrs, ATTR_CONTEXTHANDLE ) &&
         !is_attr( attrs, ATTR_CONTEXTHANDLE ))
-        flags |= 0x80;
+        flags |= HANDLE_PARAM_IS_VIA_PTR;
 
-    if (is_attr(attrs, ATTR_IN))
+    if (is_return) return flags | HANDLE_PARAM_IS_OUT | HANDLE_PARAM_IS_RETURN;
+
+    is_out = is_attr(attrs, ATTR_OUT);
+    if (is_attr(attrs, ATTR_IN) || !is_out)
     {
-        flags |= 0x40;
-        if (!is_attr(attrs, ATTR_OUT)) flags |= NDR_CONTEXT_HANDLE_CANNOT_BE_NULL;
+        flags |= HANDLE_PARAM_IS_IN;
+        if (!is_out) flags |= NDR_CONTEXT_HANDLE_CANNOT_BE_NULL;
     }
-    if (is_attr(attrs, ATTR_OUT)) flags |= 0x20;
+    if (is_out) flags |= HANDLE_PARAM_IS_OUT;
 
     return flags;
 }
@@ -490,14 +495,14 @@ unsigned char get_struct_fc(const type_t *type)
 
   if (fields) LIST_FOR_EACH_ENTRY( field, fields, var_t, entry )
   {
-    type_t *t = field->type;
+    type_t *t = field->declspec.type;
     enum typegen_type typegen_type;
 
     typegen_type = typegen_detect_type(t, field->attrs, TDT_IGNORE_STRINGS);
 
     if (typegen_type == TGT_ARRAY && !type_array_is_decl_as_ptr(t))
     {
-        if (is_string_type(field->attrs, field->type))
+        if (is_string_type(field->attrs, field->declspec.type))
         {
             if (is_conformant_array(t))
                 has_conformance = 1;
@@ -505,10 +510,10 @@ unsigned char get_struct_fc(const type_t *type)
             continue;
         }
 
-        if (is_array(type_array_get_element(field->type)))
+        if (is_array(type_array_get_element_type(field->declspec.type)))
             return FC_BOGUS_STRUCT;
 
-        if (type_array_has_conformance(field->type))
+        if (type_array_has_conformance(field->declspec.type))
         {
             has_conformance = 1;
             if (list_next(fields, &field->entry))
@@ -518,7 +523,7 @@ unsigned char get_struct_fc(const type_t *type)
         if (type_array_has_variance(t))
             has_variance = 1;
 
-        t = type_array_get_element(t);
+        t = type_array_get_element_type(t);
         typegen_type = typegen_detect_type(t, field->attrs, TDT_IGNORE_STRINGS);
     }
 
@@ -620,7 +625,7 @@ static unsigned char get_array_fc(const type_t *type)
     const expr_t *size_is;
     const type_t *elem_type;
 
-    elem_type = type_array_get_element(type);
+    elem_type = type_array_get_element_type(type);
     size_is = type_array_get_conformance(type);
 
     if (!size_is)
@@ -709,14 +714,14 @@ static int type_has_pointers(const type_t *type)
     case TGT_POINTER:
         return TRUE;
     case TGT_ARRAY:
-        return type_array_is_decl_as_ptr(type) || type_has_pointers(type_array_get_element(type));
+        return type_array_is_decl_as_ptr(type) || type_has_pointers(type_array_get_element_type(type));
     case TGT_STRUCT:
     {
         var_list_t *fields = type_struct_get_fields(type);
         const var_t *field;
         if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
         {
-            if (type_has_pointers(field->type))
+            if (type_has_pointers(field->declspec.type))
                 return TRUE;
         }
         break;
@@ -728,7 +733,7 @@ static int type_has_pointers(const type_t *type)
         fields = type_union_get_cases(type);
         if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
         {
-            if (field->type && type_has_pointers(field->type))
+            if (field->declspec.type && type_has_pointers(field->declspec.type))
                 return TRUE;
         }
         break;
@@ -763,14 +768,14 @@ static int type_has_full_pointer(const type_t *type, const attr_list_t *attrs,
         if (get_pointer_fc(type, attrs, toplevel_param) == FC_FP)
             return TRUE;
         else
-            return type_has_full_pointer(type_array_get_element(type), NULL, FALSE);
+            return type_has_full_pointer(type_array_get_element_type(type), NULL, FALSE);
     case TGT_STRUCT:
     {
         var_list_t *fields = type_struct_get_fields(type);
         const var_t *field;
         if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
         {
-            if (type_has_full_pointer(field->type, field->attrs, FALSE))
+            if (type_has_full_pointer(field->declspec.type, field->attrs, FALSE))
                 return TRUE;
         }
         break;
@@ -782,7 +787,7 @@ static int type_has_full_pointer(const type_t *type, const attr_list_t *attrs,
         fields = type_union_get_cases(type);
         if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
         {
-            if (field->type && type_has_full_pointer(field->type, field->attrs, FALSE))
+            if (field->declspec.type && type_has_full_pointer(field->declspec.type, field->attrs, FALSE))
                 return TRUE;
         }
         break;
@@ -852,7 +857,7 @@ static const char *get_context_handle_type_name(const type_t *type)
     const type_t *t;
     for (t = type;
          is_ptr(t) || type_is_alias(t);
-         t = type_is_alias(t) ? type_alias_get_aliasee(t) : type_pointer_get_ref(t))
+         t = type_is_alias(t) ? type_alias_get_aliasee_type(t) : type_pointer_get_ref_type(t))
         if (is_attr(t->attrs, ATTR_CONTEXTHANDLE))
             return t->name;
     assert(0);
@@ -902,16 +907,16 @@ static void write_var_init(FILE *file, int indent, const type_t *t, const char *
 
 void write_parameters_init(FILE *file, int indent, const var_t *func, const char *local_var_prefix)
 {
-    const var_t *var = type_function_get_retval(func->type);
+    const var_t *var = type_function_get_retval(func->declspec.type);
 
-    if (!is_void(var->type))
-        write_var_init(file, indent, var->type, var->name, local_var_prefix);
+    if (!is_void(var->declspec.type))
+        write_var_init(file, indent, var->declspec.type, var->name, local_var_prefix);
 
-    if (!type_get_function_args(func->type))
+    if (!type_function_get_args(func->declspec.type))
         return;
 
-    LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
-        write_var_init(file, indent, var->type, var->name, local_var_prefix);
+    LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), const var_t, entry )
+        write_var_init(file, indent, var->declspec.type, var->name, local_var_prefix);
 
     fprintf(file, "\n");
 }
@@ -975,14 +980,14 @@ static unsigned char get_parameter_fc( const var_t *var, int is_return, unsigned
     if (is_out)    *flags |= IsOut;
     if (is_return) *flags |= IsReturn;
 
-    if (!is_string_type( var->attrs, var->type ))
-        buffer_size = get_required_buffer_size_type( var->type, NULL, var->attrs, TRUE, &alignment );
+    if (!is_string_type( var->attrs, var->declspec.type ))
+        buffer_size = get_required_buffer_size_type( var->declspec.type, NULL, var->attrs, TRUE, &alignment );
 
-    switch (typegen_detect_type( var->type, var->attrs, TDT_ALL_TYPES ))
+    switch (typegen_detect_type( var->declspec.type, var->attrs, TDT_ALL_TYPES ))
     {
     case TGT_BASIC:
         *flags |= IsBasetype;
-        fc = get_basic_fc_signed( var->type );
+        fc = get_basic_fc_signed( var->declspec.type );
         if (fc == FC_BIND_PRIMITIVE)
         {
             buffer_size = 4;  /* actually 0 but avoids setting MustSize */
@@ -991,7 +996,7 @@ static unsigned char get_parameter_fc( const var_t *var, int is_return, unsigned
         break;
     case TGT_ENUM:
         *flags |= IsBasetype;
-        fc = get_enum_fc( var->type );
+        fc = get_enum_fc( var->declspec.type );
         break;
     case TGT_RANGE:
         *flags |= IsByValue;
@@ -1006,19 +1011,19 @@ static unsigned char get_parameter_fc( const var_t *var, int is_return, unsigned
         break;
     case TGT_ARRAY:
         *flags |= MustFree;
-        if (type_array_is_decl_as_ptr(var->type) && var->type->details.array.ptr_tfsoff &&
-            get_pointer_fc( var->type, var->attrs, !is_return ) == FC_RP)
+        if (type_array_is_decl_as_ptr(var->declspec.type) && type_get_details(var->declspec.type)->array.ptr_tfsoff &&
+            get_pointer_fc( var->declspec.type, var->attrs, !is_return ) == FC_RP)
         {
-            *typestring_offset = var->type->typestring_offset;
+            *typestring_offset = var->declspec.type->typestring_offset;
             *flags |= IsSimpleRef;
         }
         break;
     case TGT_STRING:
         *flags |= MustFree;
-        if (is_declptr( var->type ) && get_pointer_fc( var->type, var->attrs, !is_return ) == FC_RP)
+        if (is_declptr( var->declspec.type ) && get_pointer_fc( var->declspec.type, var->attrs, !is_return ) == FC_RP)
         {
             /* skip over pointer description straight to string description */
-            if (is_conformant_array( var->type )) *typestring_offset += 4;
+            if (is_conformant_array( var->declspec.type )) *typestring_offset += 4;
             else *typestring_offset += 2;
             *flags |= IsSimpleRef;
         }
@@ -1031,9 +1036,9 @@ static unsigned char get_parameter_fc( const var_t *var, int is_return, unsigned
         buffer_size = 20;
         break;
     case TGT_POINTER:
-        if (get_pointer_fc( var->type, var->attrs, !is_return ) == FC_RP)
+        if (get_pointer_fc( var->declspec.type, var->attrs, !is_return ) == FC_RP)
         {
-            const type_t *ref = type_pointer_get_ref( var->type );
+            const type_t *ref = type_pointer_get_ref_type( var->declspec.type );
 
             if (!is_string_type( var->attrs, ref ))
                 buffer_size = get_required_buffer_size_type( ref, NULL, NULL, TRUE, &alignment );
@@ -1059,11 +1064,19 @@ static unsigned char get_parameter_fc( const var_t *var, int is_return, unsigned
             case TGT_UNION:
             case TGT_USER_TYPE:
             case TGT_RANGE:
-            case TGT_ARRAY:
-                *flags |= IsSimpleRef | MustFree;
+                *flags |= MustFree | IsSimpleRef;
                 *typestring_offset = ref->typestring_offset;
                 if (!is_in && is_out) server_size = type_memsize( ref );
                 break;
+            case TGT_ARRAY:
+                *flags |= MustFree;
+                if (!type_array_is_decl_as_ptr(ref))
+                {
+                    *flags |= IsSimpleRef;
+                    *typestring_offset = ref->typestring_offset;
+                }
+                if (!is_in && is_out) server_size = type_memsize( ref );
+                break;
             case TGT_STRING:
             case TGT_POINTER:
             case TGT_CTXT_HANDLE:
@@ -1115,8 +1128,8 @@ static unsigned char get_parameter_fc( const var_t *var, int is_return, unsigned
 static unsigned char get_func_oi2_flags( const var_t *func )
 {
     const var_t *var;
-    var_list_t *args = type_get_function_args( func->type );
-    var_t *retval = type_function_get_retval( func->type );
+    var_list_t *args = type_function_get_args( func->declspec.type );
+    var_t *retval = type_function_get_retval( func->declspec.type );
     unsigned char oi2_flags = 0x40;  /* HasExtensions */
     unsigned short flags;
     unsigned int stack_size, typestring_offset;
@@ -1131,7 +1144,7 @@ static unsigned char get_func_oi2_flags( const var_t *func )
         }
     }
 
-    if (!is_void( retval->type ))
+    if (!is_void( retval->declspec.type ))
     {
         oi2_flags |= 0x04;  /* HasRet */
         get_parameter_fc( retval, 1, &flags, &stack_size, &typestring_offset );
@@ -1185,8 +1198,8 @@ static unsigned int write_old_procformatstring_type(FILE *file, int indent, cons
 
     if (!is_in && !is_out) is_in = TRUE;
 
-    if (type_get_type(var->type) == TYPE_BASIC ||
-        type_get_type(var->type) == TYPE_ENUM)
+    if (type_get_type(var->declspec.type) == TYPE_BASIC ||
+        type_get_type(var->declspec.type) == TYPE_ENUM)
     {
         unsigned char fc;
 
@@ -1195,13 +1208,13 @@ static unsigned int write_old_procformatstring_type(FILE *file, int indent, cons
         else
             print_file(file, indent, "0x4e,    /* FC_IN_PARAM_BASETYPE */\n");
 
-        if (type_get_type(var->type) == TYPE_ENUM)
+        if (type_get_type(var->declspec.type) == TYPE_ENUM)
         {
-            fc = get_enum_fc(var->type);
+            fc = get_enum_fc(var->declspec.type);
         }
         else
         {
-            fc = get_basic_fc_signed(var->type);
+            fc = get_basic_fc_signed(var->declspec.type);
 
             if (fc == FC_BIND_PRIMITIVE)
                 fc = FC_IGNORE;
@@ -1215,10 +1228,12 @@ static unsigned int write_old_procformatstring_type(FILE *file, int indent, cons
     {
         unsigned short offset = var->typestring_offset;
 
-        if (!is_interpreted && is_array(var->type) &&
-            type_array_is_decl_as_ptr(var->type) &&
-            var->type->details.array.ptr_tfsoff)
-            offset = var->type->typestring_offset;
+        if (!is_interpreted && is_array(var->declspec.type) &&
+            type_array_is_decl_as_ptr(var->declspec.type) &&
+            type_get_details(var->declspec.type)->array.ptr_tfsoff)
+        {
+            offset = var->declspec.type->typestring_offset;
+        }
 
         if (is_return)
             print_file(file, indent, "0x52,    /* FC_RETURN_PARAM */\n");
@@ -1241,8 +1256,8 @@ int is_interpreted_func( const type_t *iface, const var_t *func )
 {
     const char *str;
     const var_t *var;
-    const var_list_t *args = type_get_function_args( func->type );
-    const type_t *ret_type = type_function_get_rettype( func->type );
+    const var_list_t *args = type_function_get_args( func->declspec.type );
+    const type_t *ret_type = type_function_get_rettype( func->declspec.type );
 
     if (type_get_type( ret_type ) == TYPE_BASIC)
     {
@@ -1264,10 +1279,10 @@ int is_interpreted_func( const type_t *iface, const var_t *func )
     if (get_stub_mode() != MODE_Oif && args)
     {
         LIST_FOR_EACH_ENTRY( var, args, const var_t, entry )
-            switch (type_get_type( var->type ))
+            switch (type_get_type( var->declspec.type ))
             {
             case TYPE_BASIC:
-                switch (type_basic_get_type( var->type ))
+                switch (type_basic_get_type( var->declspec.type ))
                 {
                 /* floating point arguments are not supported in Oi mode */
                 case TYPE_BASIC_FLOAT:  return 0;
@@ -1292,7 +1307,7 @@ static void write_proc_func_header( FILE *file, int indent, const type_t *iface,
                                     unsigned short num_proc )
 {
     var_t *var;
-    var_list_t *args = type_get_function_args( func->type );
+    var_list_t *args = type_function_get_args( func->declspec.type );
     unsigned char explicit_fc, implicit_fc;
     unsigned char handle_flags;
     const var_t *handle_var = get_func_handle_var( iface, func, &explicit_fc, &implicit_fc );
@@ -1323,7 +1338,7 @@ static void write_proc_func_header( FILE *file, int indent, const type_t *iface,
         param_num++;
         nb_args++;
     }
-    if (!is_void( type_function_get_rettype( func->type )))
+    if (!is_void( type_function_get_rettype( func->declspec.type )))
     {
         stack_size += pointer_size;
         nb_args++;
@@ -1351,22 +1366,22 @@ static void write_proc_func_header( FILE *file, int indent, const type_t *iface,
             *offset += 4;
             break;
         case FC_BIND_GENERIC:
-            handle_flags = type_memsize( handle_var->type );
+            handle_flags = type_memsize( handle_var->declspec.type );
             print_file( file, indent, "0x%02x,\t/* %s */\n", explicit_fc, string_of_type(explicit_fc) );
             print_file( file, indent, "0x%02x,\n", handle_flags );
             print_file( file, indent, "NdrFcShort(0x%hx),\t/* stack offset = %hu */\n",
                         handle_stack_offset, handle_stack_offset );
-            print_file( file, indent, "0x%02x,\n", get_generic_handle_offset( handle_var->type ) );
+            print_file( file, indent, "0x%02x,\n", get_generic_handle_offset( handle_var->declspec.type ) );
             print_file( file, indent, "0x%x,\t/* FC_PAD */\n", FC_PAD);
             *offset += 6;
             break;
         case FC_BIND_CONTEXT:
-            handle_flags = get_contexthandle_flags( iface, handle_var->attrs, handle_var->type );
+            handle_flags = get_contexthandle_flags( iface, handle_var->attrs, handle_var->declspec.type, 0 );
             print_file( file, indent, "0x%02x,\t/* %s */\n", explicit_fc, string_of_type(explicit_fc) );
             print_file( file, indent, "0x%02x,\n", handle_flags );
             print_file( file, indent, "NdrFcShort(0x%hx),\t/* stack offset = %hu */\n",
                         handle_stack_offset, handle_stack_offset );
-            print_file( file, indent, "0x%02x,\n", get_context_handle_offset( handle_var->type ) );
+            print_file( file, indent, "0x%02x,\n", get_context_handle_offset( handle_var->declspec.type ) );
             print_file( file, indent, "0x%02x,\t/* param %hu */\n", handle_param_num, handle_param_num );
             *offset += 6;
             break;
@@ -1381,7 +1396,7 @@ static void write_proc_func_header( FILE *file, int indent, const type_t *iface,
 
         if (is_attr( func->attrs, ATTR_NOTIFY )) ext_flags |= 0x08;  /* HasNotify */
         if (is_attr( func->attrs, ATTR_NOTIFYFLAG )) ext_flags |= 0x10;  /* HasNotify2 */
-        if (iface == iface->details.iface->async_iface) oi2_flags |= 0x20;
+        if (iface == type_get_const_details(iface)->iface->async_iface) oi2_flags |= 0x20;
 
         size = get_function_buffer_size( func, PASS_IN );
         print_file( file, indent, "NdrFcShort(0x%x),\t/* client buffer = %u */\n", size, size );
@@ -1402,9 +1417,9 @@ static void write_proc_func_header( FILE *file, int indent, const type_t *iface,
             if (is_object( iface )) pos += 2;
             if (args) LIST_FOR_EACH_ENTRY( var, args, var_t, entry )
             {
-                if (type_get_type( var->type ) == TYPE_BASIC)
+                if (type_get_type( var->declspec.type ) == TYPE_BASIC)
                 {
-                    switch (type_basic_get_type( var->type ))
+                    switch (type_basic_get_type( var->declspec.type ))
                     {
                     case TYPE_BASIC_FLOAT:  fpu_mask |= 1 << pos; break;
                     case TYPE_BASIC_DOUBLE: fpu_mask |= 2 << pos; break;
@@ -1427,15 +1442,15 @@ static void write_procformatstring_func( FILE *file, int indent, const type_t *i
     unsigned int stack_offset = is_object( iface ) ? pointer_size : 0;
     int is_interpreted = is_interpreted_func( iface, func );
     int is_new_style = is_interpreted && (get_stub_mode() == MODE_Oif);
-    var_t *retval = type_function_get_retval( func->type );
+    var_t *retval = type_function_get_retval( func->declspec.type );
 
     if (is_interpreted) write_proc_func_header( file, indent, iface, func, offset, num_proc );
 
     /* emit argument data */
-    if (type_get_function_args(func->type))
+    if (type_function_get_args(func->declspec.type))
     {
         const var_t *var;
-        LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
+        LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), const var_t, entry )
         {
             print_file( file, 0, "/* %u (parameter %s) */\n", *offset, var->name );
             if (is_new_style)
@@ -1446,7 +1461,7 @@ static void write_procformatstring_func( FILE *file, int indent, const type_t *i
     }
 
     /* emit return value data */
-    if (is_void(retval->type))
+    if (is_void(retval->declspec.type))
     {
         if (!is_new_style)
         {
@@ -1475,13 +1490,13 @@ static void for_each_iface(const statement_list_t *stmts,
 
     if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
     {
-        if (stmt->type != STMT_TYPE || type_get_type(stmt->u.type) != TYPE_INTERFACE)
+        if (stmt->type != STMT_TYPE || type_get_type_detect_alias(stmt->u.type) != TYPE_INTERFACE)
             continue;
         iface = stmt->u.type;
         if (!pred(iface)) continue;
         proc(iface, file, indent, offset);
-        if (iface->details.iface->async_iface)
-            proc(iface->details.iface->async_iface, file, indent, offset);
+        if (type_get_const_details(iface)->iface->async_iface)
+            proc(type_get_const_details(iface)->iface->async_iface, file, indent, offset);
     }
 }
 
@@ -1593,7 +1608,7 @@ static unsigned int write_conf_or_var_desc(FILE *file, const type_t *cont_type,
     {
         conftype = FC_TOP_LEVEL_CONFORMANCE;
         conftype_string = "parameter";
-        cont_type = current_func->type;
+        cont_type = current_func->declspec.type;
         name = current_func->name;
         iface = current_iface;
     }
@@ -1656,7 +1671,7 @@ static unsigned int write_conf_or_var_desc(FILE *file, const type_t *cont_type,
 
         if (type_get_type(cont_type) == TYPE_FUNCTION)
         {
-            var_list_t *args = type_get_function_args( cont_type );
+            var_list_t *args = type_function_get_args( cont_type );
 
             if (is_object( iface )) offset += pointer_size;
             if (args) LIST_FOR_EACH_ENTRY( var, args, const var_t, entry )
@@ -1664,7 +1679,7 @@ static unsigned int write_conf_or_var_desc(FILE *file, const type_t *cont_type,
                 if (var->name && !strcmp(var->name, subexpr->u.sval))
                 {
                     expr_loc.v = var;
-                    correlation_variable = var->type;
+                    correlation_variable = var->declspec.type;
                     break;
                 }
                 offset += get_stack_size( var, NULL );
@@ -1676,11 +1691,11 @@ static unsigned int write_conf_or_var_desc(FILE *file, const type_t *cont_type,
 
             if (fields) LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry )
             {
-                unsigned int size = field_memsize( var->type, &offset );
+                unsigned int size = field_memsize( var->declspec.type, &offset );
                 if (var->name && !strcmp(var->name, subexpr->u.sval))
                 {
                     expr_loc.v = var;
-                    correlation_variable = var->type;
+                    correlation_variable = var->declspec.type;
                     break;
                 }
                 offset += size;
@@ -1819,7 +1834,7 @@ static unsigned int fields_memsize(const var_list_t *fields, unsigned int *align
     LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
     {
         unsigned int falign = 0;
-        unsigned int fsize = type_memsize_and_alignment(v->type, &falign);
+        unsigned int fsize = type_memsize_and_alignment(v->declspec.type, &falign);
         if (*align < falign) *align = falign;
         falign = clamp_align(falign);
         size = ROUND_SIZE(size, falign);
@@ -1841,9 +1856,9 @@ static unsigned int union_memsize(const var_list_t *fields, unsigned int *pmaxa)
     if (fields) LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
     {
         /* we could have an empty default field with NULL type */
-        if (v->type)
+        if (v->declspec.type)
         {
-            size = type_memsize_and_alignment(v->type, &align);
+            size = type_memsize_and_alignment(v->declspec.type, &align);
             if (maxs < size) maxs = size;
             if (*pmaxa < align) *pmaxa = align;
         }
@@ -1931,12 +1946,12 @@ unsigned int type_memsize_and_alignment(const type_t *t, unsigned int *align)
         {
             if (is_conformant_array(t))
             {
-                type_memsize_and_alignment(type_array_get_element(t), align);
+                type_memsize_and_alignment(type_array_get_element_type(t), align);
                 size = 0;
             }
             else
                 size = type_array_get_dim(t) *
-                    type_memsize_and_alignment(type_array_get_element(t), align);
+                    type_memsize_and_alignment(type_array_get_element_type(t), align);
         }
         else /* declared as a pointer */
         {
@@ -2016,8 +2031,8 @@ static unsigned int type_buffer_alignment(const type_t *t)
         if (!(fields = type_struct_get_fields(t))) break;
         LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry )
         {
-            if (!var->type) continue;
-            align = type_buffer_alignment( var->type );
+            if (!var->declspec.type) continue;
+            align = type_buffer_alignment( var->declspec.type );
             if (max < align) max = align;
         }
         break;
@@ -2025,8 +2040,8 @@ static unsigned int type_buffer_alignment(const type_t *t)
         if (!(fields = type_encapsulated_union_get_fields(t))) break;
         LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry )
         {
-            if (!var->type) continue;
-            align = type_buffer_alignment( var->type );
+            if (!var->declspec.type) continue;
+            align = type_buffer_alignment( var->declspec.type );
             if (max < align) max = align;
         }
         break;
@@ -2034,14 +2049,14 @@ static unsigned int type_buffer_alignment(const type_t *t)
         if (!(fields = type_union_get_cases(t))) break;
         LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry )
         {
-            if (!var->type) continue;
-            align = type_buffer_alignment( var->type );
+            if (!var->declspec.type) continue;
+            align = type_buffer_alignment( var->declspec.type );
             if (max < align) max = align;
         }
         break;
     case TYPE_ARRAY:
         if (!type_array_is_decl_as_ptr(t))
-            return type_buffer_alignment( type_array_get_element(t) );
+            return type_buffer_alignment( type_array_get_element_type(t) );
         /* else fall through */
     case TYPE_POINTER:
         return 4;
@@ -2064,12 +2079,12 @@ static unsigned int type_buffer_alignment(const type_t *t)
 int is_full_pointer_function(const var_t *func)
 {
     const var_t *var;
-    if (type_has_full_pointer(type_function_get_rettype(func->type), func->attrs, TRUE))
+    if (type_has_full_pointer(type_function_get_rettype(func->declspec.type), func->attrs, TRUE))
         return TRUE;
-    if (!type_get_function_args(func->type))
+    if (!type_function_get_args(func->declspec.type))
         return FALSE;
-    LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
-        if (type_has_full_pointer( var->type, var->attrs, TRUE ))
+    LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), const var_t, entry )
+        if (type_has_full_pointer( var->declspec.type, var->attrs, TRUE ))
             return TRUE;
     return FALSE;
 }
@@ -2114,12 +2129,13 @@ static unsigned int write_nonsimple_pointer(FILE *file, const attr_list_t *attrs
     {
         if (context == TYPE_CONTEXT_TOPLEVELPARAM && is_ptr(type) && pointer_type == FC_RP)
         {
-            switch (typegen_detect_type(type_pointer_get_ref(type), NULL, TDT_ALL_TYPES))
+            switch (typegen_detect_type(type_pointer_get_ref_type(type), NULL, TDT_ALL_TYPES))
             {
             case TGT_STRING:
             case TGT_POINTER:
             case TGT_CTXT_HANDLE:
             case TGT_CTXT_HANDLE_POINTER:
+            case TGT_ARRAY:
                 flags |= FC_ALLOCED_ON_STACK;
                 break;
             case TGT_IFACE_POINTER:
@@ -2134,7 +2150,7 @@ static unsigned int write_nonsimple_pointer(FILE *file, const attr_list_t *attrs
 
     if (is_ptr(type))
     {
-        type_t *ref = type_pointer_get_ref(type);
+        type_t *ref = type_pointer_get_ref_type(type);
         if(is_declptr(ref) && !is_user_type(ref))
             flags |= FC_POINTER_DEREF;
     }
@@ -2175,7 +2191,7 @@ static unsigned int write_simple_pointer(FILE *file, const attr_list_t *attrs,
 
     pointer_fc = get_pointer_fc_context(type, attrs, context);
 
-    ref = type_pointer_get_ref(type);
+    ref = type_pointer_get_ref_type(type);
     if (type_get_type(ref) == TYPE_ENUM)
         fc = get_enum_fc(ref);
     else
@@ -2200,22 +2216,23 @@ static unsigned int write_simple_pointer(FILE *file, const attr_list_t *attrs,
     return 4;
 }
 
-static void print_start_tfs_comment(FILE *file, type_t *t, unsigned int tfsoff)
+static void print_start_tfs_comment(FILE *file, const decl_spec_t *ds, unsigned int tfsoff)
 {
     print_file(file, 0, "/* %u (", tfsoff);
-    write_type_decl(file, t, NULL);
+    write_declspec_decl(file, ds, NULL);
     print_file(file, 0, ") */\n");
 }
 
 static unsigned int write_pointer_tfs(FILE *file, const attr_list_t *attrs,
-                                      type_t *type, unsigned int ref_offset,
+                                      const decl_spec_t *declspec, unsigned int ref_offset,
                                       enum type_context context,
                                       unsigned int *typestring_offset)
 {
     unsigned int offset = *typestring_offset;
-    type_t *ref = type_pointer_get_ref(type);
+    type_t *type = declspec->type;
+    type_t *ref = type_pointer_get_ref_type(type);
 
-    print_start_tfs_comment(file, type, offset);
+    print_start_tfs_comment(file, declspec, offset);
     update_tfsoff(type, offset, file);
 
     switch (typegen_detect_type(ref, attrs, TDT_ALL_TYPES))
@@ -2258,10 +2275,11 @@ static int user_type_has_variable_size(const type_t *t)
     return FALSE;
 }
 
-static unsigned int write_user_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
+static unsigned int write_user_tfs(FILE *file, const decl_spec_t *declspec, unsigned int *tfsoff)
 {
     unsigned int start, absoff, flags;
     const char *name = NULL;
+    type_t *type = declspec->type;
     type_t *utype = get_user_type(type, &name);
     unsigned int usize = type_memsize(utype);
     unsigned int ualign = type_buffer_alignment(utype);
@@ -2279,6 +2297,7 @@ static unsigned int write_user_tfs(FILE *file, type_t *type, unsigned int *tfsof
         type_get_type(utype) == TYPE_ENUM)
     {
         unsigned char fc;
+        decl_spec_t ds;
 
         if (type_get_type(utype) == TYPE_ENUM)
             fc = get_enum_fc(utype);
@@ -2286,7 +2305,7 @@ static unsigned int write_user_tfs(FILE *file, type_t *type, unsigned int *tfsof
             fc = get_basic_fc(utype);
 
         absoff = *tfsoff;
-        print_start_tfs_comment(file, utype, absoff);
+        print_start_tfs_comment(file, init_declspec(&ds, utype), absoff);
         print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
         print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
         *tfsoff += 2;
@@ -2294,7 +2313,10 @@ static unsigned int write_user_tfs(FILE *file, type_t *type, unsigned int *tfsof
     else
     {
         if (!processed(utype))
-            write_embedded_types(file, NULL, utype, utype->name, TRUE, tfsoff);
+        {
+            decl_spec_t ds;
+            write_embedded_types(file, NULL, init_declspec(&ds, utype), utype->name, TRUE, tfsoff);
+        }
         absoff = utype->typestring_offset;
     }
 
@@ -2307,7 +2329,7 @@ static unsigned int write_user_tfs(FILE *file, type_t *type, unsigned int *tfsof
 
     start = *tfsoff;
     update_tfsoff(type, start, file);
-    print_start_tfs_comment(file, type, start);
+    print_start_tfs_comment(file, declspec, start);
     print_file(file, 2, "0x%x,\t/* FC_USER_MARSHAL */\n", FC_USER_MARSHAL);
     print_file(file, 2, "0x%x,\t/* Alignment= %d, Flags= %02x */\n",
                flags | (ualign - 1), ualign - 1, flags);
@@ -2364,11 +2386,12 @@ static void write_member_type(FILE *file, const type_t *cont,
 static void write_array_element_type(FILE *file, const attr_list_t *attrs, const type_t *type,
                                      int cont_is_complex, unsigned int *tfsoff)
 {
-    type_t *elem = type_array_get_element(type);
+    const decl_spec_t *element = type_array_get_element(type);
+    type_t *elem = element->type;
 
     if (!is_embedded_complex(elem) && is_ptr(elem))
     {
-        type_t *ref = type_pointer_get_ref(elem);
+        type_t *ref = type_pointer_get_ref_type(elem);
 
         if (processed(ref))
         {
@@ -2378,7 +2401,7 @@ static void write_array_element_type(FILE *file, const attr_list_t *attrs, const
         }
         if (cont_is_complex && is_string_type(attrs, elem))
         {
-            write_string_tfs(file, NULL, elem, TYPE_CONTEXT_CONTAINER, NULL, tfsoff);
+            write_string_tfs(file, NULL, element, TYPE_CONTEXT_CONTAINER, NULL, tfsoff);
             return;
         }
         if (!is_string_type(NULL, elem) &&
@@ -2410,7 +2433,7 @@ static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff)
 
     if (fs) LIST_FOR_EACH_ENTRY(f, fs, var_t, entry)
     {
-        type_t *ft = f->type;
+        type_t *ft = f->declspec.type;
         unsigned int size = field_memsize( ft, &offset );
         if (type_get_type(ft) == TYPE_UNION && is_attr(f->attrs, ATTR_SWITCHIS))
         {
@@ -2433,13 +2456,14 @@ static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff)
 }
 
 static int write_pointer_description_offsets(
-    FILE *file, const attr_list_t *attrs, type_t *type,
+    FILE *file, const attr_list_t *attrs, const decl_spec_t *declspec,
     unsigned int *offset_in_memory, unsigned int *offset_in_buffer,
     unsigned int *typestring_offset)
 {
+    type_t *type = declspec->type;
     int written = 0;
 
-    if ((is_ptr(type) && type_get_type(type_pointer_get_ref(type)) != TYPE_INTERFACE) ||
+    if ((is_ptr(type) && type_get_type(type_pointer_get_ref_type(type)) != TYPE_INTERFACE) ||
         (is_array(type) && type_array_is_decl_as_ptr(type)))
     {
         if (offset_in_memory && offset_in_buffer)
@@ -2464,10 +2488,10 @@ static int write_pointer_description_offsets(
 
         if (is_ptr(type))
         {
-            type_t *ref = type_pointer_get_ref(type);
+            type_t *ref = type_pointer_get_ref_type(type);
 
             if (is_string_type(attrs, type))
-                write_string_tfs(file, attrs, type, TYPE_CONTEXT_CONTAINER, NULL, typestring_offset);
+                write_string_tfs(file, attrs, declspec, TYPE_CONTEXT_CONTAINER, NULL, typestring_offset);
             else if (processed(ref))
                 write_nonsimple_pointer(file, attrs, type, TYPE_CONTEXT_CONTAINER,
                                         ref->typestring_offset, typestring_offset);
@@ -2505,13 +2529,13 @@ static int write_pointer_description_offsets(
             {
                 unsigned int padding;
                 unsigned int align = 0;
-                type_memsize_and_alignment(v->type, &align);
+                type_memsize_and_alignment(v->declspec.type, &align);
                 padding = ROUNDING(*offset_in_memory, align);
                 *offset_in_memory += padding;
                 *offset_in_buffer += padding;
             }
             written += write_pointer_description_offsets(
-                file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
+                file, v->attrs, &v->declspec, offset_in_memory, offset_in_buffer,
                 typestring_offset);
         }
     }
@@ -2531,10 +2555,11 @@ static int write_pointer_description_offsets(
 }
 
 static int write_no_repeat_pointer_descriptions(
-    FILE *file, const attr_list_t *attrs, type_t *type,
+    FILE *file, const attr_list_t *attrs, const decl_spec_t *declspec,
     unsigned int *offset_in_memory, unsigned int *offset_in_buffer,
     unsigned int *typestring_offset)
 {
+    type_t *type = declspec->type;
     int written = 0;
 
     if (is_ptr(type) ||
@@ -2544,7 +2569,7 @@ static int write_no_repeat_pointer_descriptions(
         print_file(file, 2, "0x%02x, /* FC_PAD */\n", FC_PAD);
         *typestring_offset += 2;
 
-        return write_pointer_description_offsets(file, attrs, type,
+        return write_pointer_description_offsets(file, attrs, declspec,
                        offset_in_memory, offset_in_buffer, typestring_offset);
     }
 
@@ -2557,13 +2582,13 @@ static int write_no_repeat_pointer_descriptions(
             {
                 unsigned int padding;
                 unsigned int align = 0;
-                type_memsize_and_alignment(v->type, &align);
+                type_memsize_and_alignment(v->declspec.type, &align);
                 padding = ROUNDING(*offset_in_memory, align);
                 *offset_in_memory += padding;
                 *offset_in_buffer += padding;
             }
             written += write_no_repeat_pointer_descriptions(
-                file, v->attrs, v->type,
+                file, v->attrs, &v->declspec,
                 offset_in_memory, offset_in_buffer, typestring_offset);
         }
     }
@@ -2582,10 +2607,11 @@ static int write_no_repeat_pointer_descriptions(
 /* Note: if file is NULL return value is number of pointers to write, else
  * it is the number of type format characters written */
 static int write_fixed_array_pointer_descriptions(
-    FILE *file, const attr_list_t *attrs, type_t *type,
+    FILE *file, const attr_list_t *attrs, const decl_spec_t *declspec,
     unsigned int *offset_in_memory, unsigned int *offset_in_buffer,
     unsigned int *typestring_offset)
 {
+    type_t *type = declspec->type;
     int pointer_count = 0;
 
     if (type_get_type(type) == TYPE_ARRAY &&
@@ -2602,7 +2628,7 @@ static int write_fixed_array_pointer_descriptions(
             unsigned int offset_of_array_pointer_mem = 0;
             unsigned int offset_of_array_pointer_buf = 0;
 
-            increment_size = type_memsize(type_array_get_element(type));
+            increment_size = type_memsize(type_array_get_element_type(type));
 
             print_file(file, 2, "0x%02x, /* FC_FIXED_REPEAT */\n", FC_FIXED_REPEAT);
             print_file(file, 2, "0x%02x, /* FC_PAD */\n", FC_PAD);
@@ -2613,7 +2639,7 @@ static int write_fixed_array_pointer_descriptions(
             *typestring_offset += 10;
 
             pointer_count = write_pointer_description_offsets(
-                file, attrs, type, &offset_of_array_pointer_mem,
+                file, attrs, declspec, &offset_of_array_pointer_mem,
                 &offset_of_array_pointer_buf, typestring_offset);
         }
     }
@@ -2626,13 +2652,13 @@ static int write_fixed_array_pointer_descriptions(
             {
                 unsigned int padding;
                 unsigned int align = 0;
-                type_memsize_and_alignment(v->type, &align);
+                type_memsize_and_alignment(v->declspec.type, &align);
                 padding = ROUNDING(*offset_in_memory, align);
                 *offset_in_memory += padding;
                 *offset_in_buffer += padding;
             }
             pointer_count += write_fixed_array_pointer_descriptions(
-                file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
+                file, v->attrs, &v->declspec, offset_in_memory, offset_in_buffer,
                 typestring_offset);
         }
     }
@@ -2673,7 +2699,7 @@ static int write_conformant_array_pointer_descriptions(
             unsigned int offset_of_array_pointer_mem = offset_in_memory;
             unsigned int offset_of_array_pointer_buf = offset_in_memory;
 
-            increment_size = type_memsize(type_array_get_element(type));
+            increment_size = type_memsize(type_array_get_element_type(type));
 
             if (increment_size > USHRT_MAX)
                 error("array size of %u bytes is too large\n", increment_size);
@@ -2715,7 +2741,7 @@ static int write_varying_array_pointer_descriptions(
         {
             unsigned int increment_size;
 
-            increment_size = type_memsize(type_array_get_element(type));
+            increment_size = type_memsize(type_array_get_element_type(type));
 
             if (increment_size > USHRT_MAX)
                 error("array size of %u bytes is too large\n", increment_size);
@@ -2741,20 +2767,20 @@ static int write_varying_array_pointer_descriptions(
             {
                 unsigned int align = 0, padding;
 
-                if (is_array(v->type) && type_array_has_variance(v->type))
+                if (is_array(v->declspec.type) && type_array_has_variance(v->declspec.type))
                 {
                     *offset_in_buffer = ROUND_SIZE(*offset_in_buffer, 4);
                     /* skip over variance and offset in buffer */
                     *offset_in_buffer += 8;
                 }
 
-                type_memsize_and_alignment(v->type, &align);
+                type_memsize_and_alignment(v->declspec.type, &align);
                 padding = ROUNDING(*offset_in_memory, align);
                 *offset_in_memory += padding;
                 *offset_in_buffer += padding;
             }
             pointer_count += write_varying_array_pointer_descriptions(
-                file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
+                file, v->attrs, v->declspec.type, offset_in_memory, offset_in_buffer,
                 typestring_offset);
         }
     }
@@ -2773,9 +2799,10 @@ static int write_varying_array_pointer_descriptions(
     return pointer_count;
 }
 
-static void write_pointer_description(FILE *file, const attr_list_t *attrs, type_t *type,
+static void write_pointer_description(FILE *file, const attr_list_t *attrs, const decl_spec_t *declspec,
                                       unsigned int *typestring_offset)
 {
+    type_t *type = declspec->type;
     unsigned int offset_in_buffer;
     unsigned int offset_in_memory;
 
@@ -2786,7 +2813,7 @@ static void write_pointer_description(FILE *file, const attr_list_t *attrs, type
         offset_in_memory = 0;
         offset_in_buffer = 0;
         write_no_repeat_pointer_descriptions(
-            file, NULL, type,
+            file, NULL, declspec,
             &offset_in_memory, &offset_in_buffer, typestring_offset);
     }
 
@@ -2794,7 +2821,7 @@ static void write_pointer_description(FILE *file, const attr_list_t *attrs, type
     offset_in_memory = 0;
     offset_in_buffer = 0;
     write_fixed_array_pointer_descriptions(
-        file, NULL, type,
+        file, NULL, declspec,
         &offset_in_memory, &offset_in_buffer, typestring_offset);
 
     /* pass 3: search for pointers in conformant only arrays (but don't descend
@@ -2806,7 +2833,7 @@ static void write_pointer_description(FILE *file, const attr_list_t *attrs, type
     else if (type_get_type(type) == TYPE_STRUCT &&
              get_struct_fc(type) == FC_CPSTRUCT)
     {
-        type_t *carray = find_array_or_string_in_struct(type)->type;
+        type_t *carray = find_array_or_string_in_struct(type)->declspec.type;
         write_conformant_array_pointer_descriptions( file, NULL, carray,
                                                      type_memsize(type), typestring_offset);
     }
@@ -2820,9 +2847,10 @@ static void write_pointer_description(FILE *file, const attr_list_t *attrs, type
 }
 
 static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs,
-                                     type_t *type, enum type_context context,
+                                     const decl_spec_t *declspec, enum type_context context,
                                      const char *name, unsigned int *typestring_offset)
 {
+    type_t *type = declspec->type;
     unsigned int start_offset;
     unsigned char rtype;
     type_t *elem_type;
@@ -2836,7 +2864,7 @@ static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs,
         int pointer_type = get_pointer_fc_context(type, attrs, context);
         if (!pointer_type)
             pointer_type = FC_RP;
-        print_start_tfs_comment(file, type, *typestring_offset);
+        print_start_tfs_comment(file, declspec, *typestring_offset);
         print_file(file, 2,"0x%x, 0x%x,\t/* %s%s */\n",
                    pointer_type, flag, string_of_type(pointer_type),
                    flag ? " [simple_pointer]" : "");
@@ -2850,12 +2878,12 @@ static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs,
     }
 
     if (is_array(type))
-        elem_type = type_array_get_element(type);
+        elem_type = type_array_get_element_type(type);
     else
-        elem_type = type_pointer_get_ref(type);
+        elem_type = type_pointer_get_ref_type(type);
 
     if (type_get_type(elem_type) == TYPE_POINTER && is_array(type))
-        return write_array_tfs(file, attrs, type, name, typestring_offset);
+        return write_array_tfs(file, attrs, declspec, name, typestring_offset);
 
     if (type_get_type(elem_type) != TYPE_BASIC)
     {
@@ -2929,34 +2957,31 @@ static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs,
     }
 }
 
-static unsigned int write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
+static unsigned int write_array_tfs(FILE *file, const attr_list_t *attrs, const decl_spec_t *declspec,
                                     const char *name, unsigned int *typestring_offset)
 {
+    type_t *type = declspec->type;
     const expr_t *length_is = type_array_get_variance(type);
     const expr_t *size_is = type_array_get_conformance(type);
     unsigned int align;
     unsigned int size;
     unsigned int start_offset;
     unsigned char fc;
-    int pointer_type = get_attrv(attrs, ATTR_POINTERTYPE);
     unsigned int baseoff
         = !type_array_is_decl_as_ptr(type) && current_structure
         ? type_memsize(current_structure)
         : 0;
 
-    if (!pointer_type)
-        pointer_type = FC_RP;
-
-    if (!is_string_type(attrs, type_array_get_element(type)))
+    if (!is_string_type(attrs, type_array_get_element_type(type)))
         write_embedded_types(file, attrs, type_array_get_element(type), name, FALSE, typestring_offset);
 
-    size = type_memsize(is_conformant_array(type) ? type_array_get_element(type) : type);
-    align = type_buffer_alignment(is_conformant_array(type) ? type_array_get_element(type) : type);
+    size = type_memsize(is_conformant_array(type) ? type_array_get_element_type(type) : type);
+    align = type_buffer_alignment(is_conformant_array(type) ? type_array_get_element_type(type) : type);
     fc = get_array_fc(type);
 
     start_offset = *typestring_offset;
     update_tfsoff(type, start_offset, file);
-    print_start_tfs_comment(file, type, start_offset);
+    print_start_tfs_comment(file, declspec, start_offset);
     print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc));
     print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
     *typestring_offset += 2;
@@ -2982,7 +3007,7 @@ static unsigned int write_array_tfs(FILE *file, const attr_list_t *attrs, type_t
 
         if (fc == FC_SMVARRAY || fc == FC_LGVARRAY)
         {
-            unsigned int elsize = type_memsize(type_array_get_element(type));
+            unsigned int elsize = type_memsize(type_array_get_element_type(type));
             unsigned int dim = type_array_get_dim(type);
 
             if (fc == FC_LGVARRAY)
@@ -3005,13 +3030,13 @@ static unsigned int write_array_tfs(FILE *file, const attr_list_t *attrs, type_t
                 += write_conf_or_var_desc(file, current_structure, baseoff,
                                           type, length_is);
 
-        if (type_has_pointers(type_array_get_element(type)) &&
+        if (type_has_pointers(type_array_get_element_type(type)) &&
             (type_array_is_decl_as_ptr(type) || !current_structure))
         {
             print_file(file, 2, "0x%x,\t/* FC_PP */\n", FC_PP);
             print_file(file, 2, "0x%x,\t/* FC_PAD */\n", FC_PAD);
             *typestring_offset += 2;
-            write_pointer_description(file, is_string_type(attrs, type) ? attrs : NULL, type, typestring_offset);
+            write_pointer_description(file, is_string_type(attrs, type) ? attrs : NULL, declspec, typestring_offset);
             print_file(file, 2, "0x%x,\t/* FC_END */\n", FC_END);
             *typestring_offset += 1;
         }
@@ -3048,7 +3073,7 @@ static const var_t *find_array_or_string_in_struct(const type_t *type)
         return NULL;
 
     last_field = LIST_ENTRY( list_tail(fields), const var_t, entry );
-    ft = last_field->type;
+    ft = last_field->declspec.type;
 
     if (is_conformant_array(ft) && !type_array_is_decl_as_ptr(ft))
         return last_field;
@@ -3071,7 +3096,7 @@ static void write_struct_members(FILE *file, const type_t *type,
 
     if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
     {
-        type_t *ft = field->type;
+        type_t *ft = field->declspec.type;
         unsigned int align = 0;
         unsigned int size = type_memsize_and_alignment(ft, &align);
         align = clamp_align(align);
@@ -3100,7 +3125,7 @@ static void write_struct_members(FILE *file, const type_t *type,
                 offset = ROUND_SIZE(offset, align);
                 *typestring_offset += 1;
             }
-            write_member_type(file, type, is_complex, field->attrs, field->type, corroff,
+            write_member_type(file, type, is_complex, field->attrs, field->declspec.type, corroff,
                               typestring_offset);
             offset += size;
         }
@@ -3118,9 +3143,10 @@ static void write_struct_members(FILE *file, const type_t *type,
     write_end(file, typestring_offset);
 }
 
-static unsigned int write_struct_tfs(FILE *file, type_t *type,
+static unsigned int write_struct_tfs(FILE *file, const decl_spec_t *declspec,
                                      const char *name, unsigned int *tfsoff)
 {
+    type_t *type = declspec->type;
     const type_t *save_current_structure = current_structure;
     unsigned int total_size;
     const var_t *array;
@@ -3143,15 +3169,15 @@ static unsigned int write_struct_tfs(FILE *file, type_t *type,
               name, USHRT_MAX, total_size - USHRT_MAX);
 
     if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
-        write_embedded_types(file, f->attrs, f->type, f->name, FALSE, tfsoff);
+        write_embedded_types(file, f->attrs, &f->declspec, f->name, FALSE, tfsoff);
 
     array = find_array_or_string_in_struct(type);
-    if (array && !processed(array->type))
+    if (array && !processed(array->declspec.type))
     {
-        if(is_string_type(array->attrs, array->type))
-            write_string_tfs(file, array->attrs, array->type, TYPE_CONTEXT_CONTAINER, array->name, tfsoff);
+        if(is_string_type(array->attrs, array->declspec.type))
+            write_string_tfs(file, array->attrs, &array->declspec, TYPE_CONTEXT_CONTAINER, array->name, tfsoff);
         else
-            write_array_tfs(file, array->attrs, array->type, array->name, tfsoff);
+            write_array_tfs(file, array->attrs, &array->declspec, array->name, tfsoff);
     }
 
     corroff = *tfsoff;
@@ -3159,7 +3185,7 @@ static unsigned int write_struct_tfs(FILE *file, type_t *type,
 
     start_offset = *tfsoff;
     update_tfsoff(type, start_offset, file);
-    print_start_tfs_comment(file, type, start_offset);
+    print_start_tfs_comment(file, declspec, start_offset);
     print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
     print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
     print_file(file, 2, "NdrFcShort(0x%hx),\t/* %d */\n", (unsigned short)total_size, total_size);
@@ -3167,7 +3193,7 @@ static unsigned int write_struct_tfs(FILE *file, type_t *type,
 
     if (array)
     {
-        unsigned int absoff = array->type->typestring_offset;
+        unsigned int absoff = array->declspec.type->typestring_offset;
         short reloff = absoff - *tfsoff;
         print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
                    reloff, reloff, absoff);
@@ -3198,7 +3224,7 @@ static unsigned int write_struct_tfs(FILE *file, type_t *type,
         print_file(file, 2, "0x%x,\t/* FC_PP */\n", FC_PP);
         print_file(file, 2, "0x%x,\t/* FC_PAD */\n", FC_PAD);
         *tfsoff += 2;
-        write_pointer_description(file, NULL, type, tfsoff);
+        write_pointer_description(file, NULL, declspec, tfsoff);
         print_file(file, 2, "0x%x,\t/* FC_END */\n", FC_END);
         *tfsoff += 1;
     }
@@ -3213,15 +3239,16 @@ static unsigned int write_struct_tfs(FILE *file, type_t *type,
         type->ptrdesc = *tfsoff;
         if (fields) LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry)
         {
-            type_t *ft = f->type;
+            const decl_spec_t *fds = &f->declspec;
+            type_t *ft = fds->type;
             switch (typegen_detect_type(ft, f->attrs, TDT_IGNORE_STRINGS))
             {
             case TGT_POINTER:
                 if (is_string_type(f->attrs, ft))
-                    write_string_tfs(file, f->attrs, ft, TYPE_CONTEXT_CONTAINER, f->name, tfsoff);
+                    write_string_tfs(file, f->attrs, fds, TYPE_CONTEXT_CONTAINER, f->name, tfsoff);
                 else
-                    write_pointer_tfs(file, f->attrs, ft,
-                                      type_pointer_get_ref(ft)->typestring_offset,
+                    write_pointer_tfs(file, f->attrs, fds,
+                                      type_pointer_get_ref_type(ft)->typestring_offset,
                                       TYPE_CONTEXT_CONTAINER, tfsoff);
                 break;
             case TGT_ARRAY:
@@ -3283,8 +3310,9 @@ static void write_branch_type(FILE *file, const type_t *t, unsigned int *tfsoff)
 }
 
 static unsigned int write_union_tfs(FILE *file, const attr_list_t *attrs,
-                                    type_t *type, unsigned int *tfsoff)
+                                    const decl_spec_t *declspec, unsigned int *tfsoff)
 {
+    type_t* type = declspec->type;
     unsigned int start_offset;
     unsigned int size;
     var_list_t *fields;
@@ -3309,17 +3337,17 @@ static unsigned int write_union_tfs(FILE *file, const attr_list_t *attrs,
         expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
         if (cases)
             nbranch += list_count(cases);
-        if (f->type)
-            write_embedded_types(file, f->attrs, f->type, f->name, TRUE, tfsoff);
+        if (f->declspec.type)
+            write_embedded_types(file, f->attrs, &f->declspec, f->name, TRUE, tfsoff);
     }
 
     start_offset = *tfsoff;
     update_tfsoff(type, start_offset, file);
-    print_start_tfs_comment(file, type, start_offset);
+    print_start_tfs_comment(file, declspec, start_offset);
     if (type_get_type(type) == TYPE_ENCAPSULATED_UNION)
     {
         const var_t *sv = type_union_get_switch_value(type);
-        const type_t *st = sv->type;
+        const type_t *st = sv->declspec.type;
         unsigned int align = 0;
         unsigned char fc;
 
@@ -3351,8 +3379,8 @@ static unsigned int write_union_tfs(FILE *file, const attr_list_t *attrs,
         type_memsize_and_alignment(st, &align);
         if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
         {
-            if (f->type)
-                type_memsize_and_alignment(f->type, &align);
+            if (f->declspec.type)
+                type_memsize_and_alignment(f->declspec.type, &align);
         }
 
         print_file(file, 2, "0x%x,\t/* FC_ENCAPSULATED_UNION */\n", FC_ENCAPSULATED_UNION);
@@ -3407,7 +3435,7 @@ static unsigned int write_union_tfs(FILE *file, const attr_list_t *attrs,
 
     if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
     {
-        type_t *ft = f->type;
+        type_t *ft = f->declspec.type;
         expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
         int deflt = is_attr(f->attrs, ATTR_DEFAULT);
         expr_t *c;
@@ -3448,16 +3476,17 @@ static unsigned int write_union_tfs(FILE *file, const attr_list_t *attrs,
     return start_offset;
 }
 
-static unsigned int write_ip_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
+static unsigned int write_ip_tfs(FILE *file, const attr_list_t *attrs, const decl_spec_t *declspec,
                                  unsigned int *typeformat_offset)
 {
     unsigned int i;
+    type_t *type = declspec->type;
     unsigned int start_offset = *typeformat_offset;
     expr_t *iid = get_attrp(attrs, ATTR_IIDIS);
 
     if (!iid && processed(type)) return type->typestring_offset;
 
-    print_start_tfs_comment(file, type, start_offset);
+    print_start_tfs_comment(file, declspec, start_offset);
     update_tfsoff(type, start_offset, file);
 
     if (iid)
@@ -3469,7 +3498,7 @@ static unsigned int write_ip_tfs(FILE *file, const attr_list_t *attrs, type_t *t
     }
     else
     {
-        const type_t *base = is_ptr(type) ? type_pointer_get_ref(type) : type;
+        const type_t *base = is_ptr(type) ? type_pointer_get_ref_type(type) : type;
         const UUID *uuid = get_attrp(base->attrs, ATTR_UUID);
 
         if (! uuid)
@@ -3493,18 +3522,19 @@ static unsigned int write_ip_tfs(FILE *file, const attr_list_t *attrs, type_t *t
 
 static unsigned int write_contexthandle_tfs(FILE *file,
                                             const attr_list_t *attrs,
-                                            type_t *type,
-                                            int toplevel_param,
+                                            const decl_spec_t *declspec,
+                                            enum type_context context,
                                             unsigned int *typeformat_offset)
 {
+    type_t *type = declspec->type;
     unsigned int start_offset = *typeformat_offset;
-    unsigned char flags = get_contexthandle_flags( current_iface, attrs, type );
+    unsigned char flags = get_contexthandle_flags( current_iface, attrs, type, context == TYPE_CONTEXT_RETVAL );
 
-    print_start_tfs_comment(file, type, start_offset);
+    print_start_tfs_comment(file, declspec, start_offset);
 
     if (flags & 0x80)  /* via ptr */
     {
-        int pointer_type = get_pointer_fc( type, attrs, toplevel_param );
+        int pointer_type = get_pointer_fc( type, attrs, context == TYPE_CONTEXT_TOPLEVELPARAM );
         if (!pointer_type) pointer_type = FC_RP;
         *typeformat_offset += 4;
         print_file(file, 2,"0x%x, 0x0,\t/* %s */\n", pointer_type, string_of_type(pointer_type) );
@@ -3514,8 +3544,7 @@ static unsigned int write_contexthandle_tfs(FILE *file,
 
     print_file(file, 2, "0x%02x,\t/* FC_BIND_CONTEXT */\n", FC_BIND_CONTEXT);
     print_file(file, 2, "0x%x,\t/* Context flags: ", flags);
-    /* return and can't be null values overlap */
-    if (((flags & 0x21) != 0x21) && (flags & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL))
+    if (flags & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL)
         print_file(file, 0, "can't be null, ");
     if (flags & NDR_CONTEXT_HANDLE_SERIALIZE)
         print_file(file, 0, "serialize, ");
@@ -3523,13 +3552,13 @@ static unsigned int write_contexthandle_tfs(FILE *file,
         print_file(file, 0, "no serialize, ");
     if (flags & NDR_STRICT_CONTEXT_HANDLE)
         print_file(file, 0, "strict, ");
-    if ((flags & 0x21) == 0x20)
-        print_file(file, 0, "out, ");
-    if ((flags & 0x21) == 0x21)
+    if (flags & HANDLE_PARAM_IS_RETURN)
         print_file(file, 0, "return, ");
-    if (flags & 0x40)
+    if (flags & HANDLE_PARAM_IS_OUT)
+        print_file(file, 0, "out, ");
+    if (flags & HANDLE_PARAM_IS_IN)
         print_file(file, 0, "in, ");
-    if (flags & 0x80)
+    if (flags & HANDLE_PARAM_IS_VIA_PTR)
         print_file(file, 0, "via ptr, ");
     print_file(file, 0, "*/\n");
     print_file(file, 2, "0x%x,\t/* rundown routine */\n", get_context_handle_offset( type ));
@@ -3568,24 +3597,23 @@ static unsigned int write_range_tfs(FILE *file, const attr_list_t *attrs,
     return start_offset;
 }
 
-static unsigned int write_type_tfs(FILE *file, int indent,
-                                   const attr_list_t *attrs, type_t *type,
-                                   const char *name,
+static unsigned int write_type_tfs(FILE *file, const attr_list_t *attrs,
+                                   const decl_spec_t *declspec, const char *name,
                                    enum type_context context,
                                    unsigned int *typeformat_offset)
 {
     unsigned int offset;
+    type_t *type = declspec->type;
 
     switch (typegen_detect_type(type, attrs, TDT_ALL_TYPES))
     {
     case TGT_CTXT_HANDLE:
     case TGT_CTXT_HANDLE_POINTER:
-        return write_contexthandle_tfs(file, attrs, type,
-                                       context == TYPE_CONTEXT_TOPLEVELPARAM, typeformat_offset);
+        return write_contexthandle_tfs(file, attrs, declspec, context, typeformat_offset);
     case TGT_USER_TYPE:
-        return write_user_tfs(file, type, typeformat_offset);
+        return write_user_tfs(file, declspec, typeformat_offset);
     case TGT_STRING:
-        return write_string_tfs(file, attrs, type, context, name, typeformat_offset);
+        return write_string_tfs(file, attrs, declspec, context, name, typeformat_offset);
     case TGT_ARRAY:
     {
         unsigned int off;
@@ -3593,15 +3621,14 @@ static unsigned int write_type_tfs(FILE *file, int indent,
         if ((context != TYPE_CONTEXT_CONTAINER &&
              context != TYPE_CONTEXT_CONTAINER_NO_POINTERS) ||
             !is_conformant_array(type) || type_array_is_decl_as_ptr(type))
-            off = write_array_tfs(file, attrs, type, name, typeformat_offset);
+            off = write_array_tfs(file, attrs, declspec, name, typeformat_offset);
         else
             off = 0;
         if (context != TYPE_CONTEXT_CONTAINER &&
             context != TYPE_CONTEXT_CONTAINER_NO_POINTERS)
         {
             int ptr_type;
-            ptr_type = get_pointer_fc(type, attrs,
-                                      context == TYPE_CONTEXT_TOPLEVELPARAM);
+            ptr_type = get_pointer_fc_context(type, attrs, context);
             if (ptr_type != FC_RP || type_array_is_decl_as_ptr(type))
             {
                 unsigned int absoff = type->typestring_offset;
@@ -3615,14 +3642,14 @@ static unsigned int write_type_tfs(FILE *file, int indent,
                 if (ptr_type != FC_RP) update_tfsoff( type, off, file );
                 *typeformat_offset += 4;
             }
-            type->details.array.ptr_tfsoff = off;
+            type_get_details(type)->array.ptr_tfsoff = off;
         }
         return off;
     }
     case TGT_STRUCT:
-        return write_struct_tfs(file, type, name, typeformat_offset);
+        return write_struct_tfs(file, declspec, name, typeformat_offset);
     case TGT_UNION:
-        return write_union_tfs(file, attrs, type, typeformat_offset);
+        return write_union_tfs(file, attrs, declspec, typeformat_offset);
     case TGT_ENUM:
     case TGT_BASIC:
         /* nothing to do */
@@ -3635,11 +3662,11 @@ static unsigned int write_type_tfs(FILE *file, int indent,
         return write_range_tfs(file, attrs, type, range_list, typeformat_offset);
     }
     case TGT_IFACE_POINTER:
-        return write_ip_tfs(file, attrs, type, typeformat_offset);
+        return write_ip_tfs(file, attrs, declspec, typeformat_offset);
     case TGT_POINTER:
     {
         enum type_context ref_context;
-        type_t *ref = type_pointer_get_ref(type);
+        const decl_spec_t *ref = type_pointer_get_ref(type);
 
         if (context == TYPE_CONTEXT_TOPLEVELPARAM)
             ref_context = TYPE_CONTEXT_PARAM;
@@ -3648,22 +3675,22 @@ static unsigned int write_type_tfs(FILE *file, int indent,
         else
             ref_context = context;
 
-        if (is_string_type(attrs, ref))
+        if (is_string_type(attrs, ref->type))
         {
             if (context != TYPE_CONTEXT_CONTAINER_NO_POINTERS)
-                write_pointer_tfs(file, attrs, type, *typeformat_offset + 4, context, typeformat_offset);
+                write_pointer_tfs(file, attrs, declspec, *typeformat_offset + 4, context, typeformat_offset);
 
-            offset = write_type_tfs(file, indent, attrs, ref, name, ref_context, typeformat_offset);
+            offset = write_type_tfs(file, attrs, ref, name, ref_context, typeformat_offset);
             if (context == TYPE_CONTEXT_CONTAINER_NO_POINTERS)
                 return 0;
             return offset;
         }
 
-        offset = write_type_tfs( file, indent, attrs, type_pointer_get_ref(type), name,
+        offset = write_type_tfs( file, attrs, type_pointer_get_ref(type), name,
                                  ref_context, typeformat_offset);
         if (context == TYPE_CONTEXT_CONTAINER_NO_POINTERS)
             return 0;
-        return write_pointer_tfs(file, attrs, type, offset, context, typeformat_offset);
+        return write_pointer_tfs(file, attrs, declspec, offset, context, typeformat_offset);
     }
     case TGT_INVALID:
         break;
@@ -3672,10 +3699,10 @@ static unsigned int write_type_tfs(FILE *file, int indent,
     return 0;
 }
 
-static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
+static int write_embedded_types(FILE *file, const attr_list_t *attrs, const decl_spec_t *declspec,
                                 const char *name, int write_ptr, unsigned int *tfsoff)
 {
-    return write_type_tfs(file, 2, attrs, type, name, write_ptr ? TYPE_CONTEXT_CONTAINER : TYPE_CONTEXT_CONTAINER_NO_POINTERS, tfsoff);
+    return write_type_tfs(file, attrs, declspec, name, write_ptr ? TYPE_CONTEXT_CONTAINER : TYPE_CONTEXT_CONTAINER_NO_POINTERS, tfsoff);
 }
 
 static void process_tfs_iface(type_t *iface, FILE *file, int indent, unsigned int *offset)
@@ -3693,21 +3720,21 @@ static void process_tfs_iface(type_t *iface, FILE *file, int indent, unsigned in
         {
             const var_t *func = stmt->u.var;
 
-            if(stmt->u.var->stgclass != STG_NONE
-               || type_get_type_detect_alias(stmt->u.var->type) != TYPE_FUNCTION)
+            if(stmt->u.var->declspec.stgclass != STG_NONE
+               || type_get_type_detect_alias(stmt->u.var->declspec.type) != TYPE_FUNCTION)
                 continue;
 
             current_func = func;
             if (is_local(func->attrs)) continue;
 
-            var = type_function_get_retval(func->type);
-            if (!is_void(var->type))
-                var->typestring_offset = write_type_tfs( file, 2, func->attrs, var->type, func->name,
-                                                         TYPE_CONTEXT_PARAM, offset);
+            var = type_function_get_retval(func->declspec.type);
+            if (!is_void(var->declspec.type))
+                var->typestring_offset = write_type_tfs( file, var->attrs, &var->declspec, func->name,
+                                                         TYPE_CONTEXT_RETVAL, offset);
 
-            if (type_get_function_args(func->type))
-                LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), var_t, entry )
-                    var->typestring_offset = write_type_tfs( file, 2, var->attrs, var->type, var->name,
+            if (type_function_get_args(func->declspec.type))
+                LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), var_t, entry )
+                    var->typestring_offset = write_type_tfs( file, var->attrs, &var->declspec, var->name,
                                                              TYPE_CONTEXT_TOPLEVELPARAM, offset );
             break;
 
@@ -3719,9 +3746,12 @@ static void process_tfs_iface(type_t *iface, FILE *file, int indent, unsigned in
             {
                 if (is_attr(type_entry->type->attrs, ATTR_ENCODE)
                     || is_attr(type_entry->type->attrs, ATTR_DECODE))
-                    type_entry->type->typestring_offset = write_type_tfs( file, 2,
-                            type_entry->type->attrs, type_entry->type, type_entry->type->name,
+                {
+                    decl_spec_t ds;
+                    type_entry->type->typestring_offset = write_type_tfs( file,
+                            type_entry->type->attrs, init_declspec(&ds, type_entry->type), type_entry->type->name,
                             TYPE_CONTEXT_CONTAINER, offset);
+                }
             }
             break;
         }
@@ -3842,7 +3872,7 @@ static unsigned int get_required_buffer_size_type(
     case TGT_POINTER:
         {
             unsigned int size, align;
-            const type_t *ref = type_pointer_get_ref(type);
+            const type_t *ref = type_pointer_get_ref_type(type);
             if (is_string_type( attrs, ref )) break;
             if (!(size = get_required_buffer_size_type( ref, name, NULL, FALSE, &align ))) break;
             if (get_pointer_fc(type, attrs, toplevel_param) != FC_RP)
@@ -3862,7 +3892,7 @@ static unsigned int get_required_buffer_size_type(
             case FC_SMFARRAY:
             case FC_LGFARRAY:
                 return type_array_get_dim(type) *
-                    get_required_buffer_size_type(type_array_get_element(type), name,
+                    get_required_buffer_size_type(type_array_get_element_type(type), name,
                                                   NULL, FALSE, alignment);
             }
         }
@@ -3893,8 +3923,8 @@ static unsigned int get_required_buffer_size(const var_t *var, unsigned int *ali
             return 20;
         }
 
-        if (!is_string_type(var->attrs, var->type))
-            return get_required_buffer_size_type(var->type, var->name,
+        if (!is_string_type(var->attrs, var->declspec.type))
+            return get_required_buffer_size_type(var->declspec.type, var->name,
                                                  var->attrs, TRUE, alignment);
     }
     return 0;
@@ -3905,19 +3935,19 @@ static unsigned int get_function_buffer_size( const var_t *func, enum pass pass
     const var_t *var;
     unsigned int total_size = 0, alignment;
 
-    if (type_get_function_args(func->type))
+    if (type_function_get_args(func->declspec.type))
     {
-        LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
+        LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), const var_t, entry )
         {
             total_size += get_required_buffer_size(var, &alignment, pass);
             total_size += alignment;
         }
     }
 
-    if (pass == PASS_OUT && !is_void(type_function_get_rettype(func->type)))
+    if (pass == PASS_OUT && !is_void(type_function_get_rettype(func->declspec.type)))
     {
         var_t v = *func;
-        v.type = type_function_get_rettype(func->type);
+        v.declspec.type = type_function_get_rettype(func->declspec.type);
         total_size += get_required_buffer_size(&v, &alignment, PASS_RETURN);
         total_size += alignment;
     }
@@ -3953,9 +3983,9 @@ static void print_phase_function(FILE *file, int indent, const char *type,
     print_file(file, indent, "&__frame->_StubMsg,\n");
     print_file(file, indent, "%s%s%s%s%s,\n",
                (phase == PHASE_UNMARSHAL) ? "(unsigned char **)" : "(unsigned char *)",
-               (phase == PHASE_UNMARSHAL || decl_indirect(var->type)) ? "&" : "",
+               (phase == PHASE_UNMARSHAL || decl_indirect(var->declspec.type)) ? "&" : "",
                local_var_prefix,
-               (phase == PHASE_UNMARSHAL && decl_indirect(var->type)) ? "_p_" : "",
+               (phase == PHASE_UNMARSHAL && decl_indirect(var->declspec.type)) ? "_p_" : "",
                var->name);
     print_file(file, indent, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
                type_offset, (phase == PHASE_UNMARSHAL) ? "," : ");");
@@ -3968,7 +3998,8 @@ void print_phase_basetype(FILE *file, int indent, const char *local_var_prefix,
                           enum remoting_phase phase, enum pass pass, const var_t *var,
                           const char *varname)
 {
-    type_t *type = var->type;
+    const decl_spec_t *declspec = &var->declspec;
+    type_t *type = declspec->type;
     unsigned int alignment = 0;
 
     /* no work to do for other phases, buffer sizing is done elsewhere */
@@ -3999,8 +4030,8 @@ void print_phase_basetype(FILE *file, int indent, const char *local_var_prefix,
     }
     else
     {
-        const type_t *ref = is_ptr(type) ? type_pointer_get_ref(type) : type;
-        switch (get_basic_fc(ref))
+        const decl_spec_t *ref = is_ptr(type) ? type_pointer_get_ref(type) : declspec;
+        switch (get_basic_fc(ref->type))
         {
         case FC_BYTE:
         case FC_CHAR:
@@ -4037,7 +4068,7 @@ void print_phase_basetype(FILE *file, int indent, const char *local_var_prefix,
 
         default:
             error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n",
-                  var->name, get_basic_fc(ref));
+                  var->name, get_basic_fc(ref->type));
         }
 
         if (phase == PHASE_MARSHAL && alignment > 1)
@@ -4048,7 +4079,7 @@ void print_phase_basetype(FILE *file, int indent, const char *local_var_prefix,
         if (phase == PHASE_MARSHAL)
         {
             print_file(file, indent, "*(");
-            write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL);
+            write_declspec_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : declspec, NULL);
             if (is_ptr(type))
                 fprintf(file, " *)__frame->_StubMsg.Buffer = *");
             else
@@ -4059,7 +4090,7 @@ void print_phase_basetype(FILE *file, int indent, const char *local_var_prefix,
         else if (phase == PHASE_UNMARSHAL)
         {
             print_file(file, indent, "if (__frame->_StubMsg.Buffer + sizeof(");
-            write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL);
+            write_declspec_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : declspec, NULL);
             fprintf(file, ") > __frame->_StubMsg.BufferEnd)\n");
             print_file(file, indent, "{\n");
             print_file(file, indent + 1, "RpcRaiseException(RPC_X_BAD_STUB_DATA);\n");
@@ -4071,12 +4102,12 @@ void print_phase_basetype(FILE *file, int indent, const char *local_var_prefix,
                 fprintf(file, " = (");
             else
                 fprintf(file, " = *(");
-            write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL);
+            write_declspec_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : declspec, NULL);
             fprintf(file, " *)__frame->_StubMsg.Buffer;\n");
         }
 
         print_file(file, indent, "__frame->_StubMsg.Buffer += sizeof(");
-        write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL);
+        write_declspec_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : declspec, NULL);
         fprintf(file, ");\n");
     }
 }
@@ -4092,7 +4123,7 @@ expr_t *get_size_is_expr(const type_t *t, const char *name)
 {
     expr_t *x = NULL;
 
-    for ( ; is_array(t); t = type_array_get_element(t))
+    for ( ; is_array(t); t = type_array_get_element_type(t))
         if (type_array_has_conformance(t) &&
             type_array_get_conformance(t)->type != EXPR_VOID)
         {
@@ -4110,7 +4141,7 @@ expr_t *get_size_is_expr(const type_t *t, const char *name)
 void write_parameter_conf_or_var_exprs(FILE *file, int indent, const char *local_var_prefix,
                                        enum remoting_phase phase, const var_t *var, int valid_variance)
 {
-    const type_t *type = var->type;
+    const type_t *type = var->declspec.type;
     /* get fundamental type for the argument */
     for (;;)
     {
@@ -4162,7 +4193,7 @@ void write_parameter_conf_or_var_exprs(FILE *file, int indent, const char *local
             break;
         }
         case TGT_POINTER:
-            type = type_pointer_get_ref(type);
+            type = type_pointer_get_ref_type(type);
             continue;
         case TGT_INVALID:
         case TGT_USER_TYPE:
@@ -4184,7 +4215,7 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const
 {
     int in_attr, out_attr, pointer_type;
     const char *type_str = NULL;
-    const type_t *type = var->type;
+    const type_t *type = var->declspec.type;
     unsigned int alignment, start_offset = type->typestring_offset;
 
     if (is_ptr(type) || is_array(type))
@@ -4237,19 +4268,20 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const
                 print_file(file, indent, "NdrServerContextNewMarshall(\n");
                 print_file(file, indent + 1, "&__frame->_StubMsg,\n");
                 print_file(file, indent + 1, "(NDR_SCONTEXT)%s%s,\n", local_var_prefix, var->name);
-                print_file(file, indent + 1, "(NDR_RUNDOWN)%s_rundown,\n", get_context_handle_type_name(var->type));
+                print_file(file, indent + 1, "(NDR_RUNDOWN)%s_rundown,\n", get_context_handle_type_name(var->declspec.type));
                 print_file(file, indent + 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset);
             }
         }
         else if (phase == PHASE_UNMARSHAL)
         {
-            if (pass == PASS_OUT)
+            if (pass == PASS_OUT || pass == PASS_RETURN)
             {
                 if (!in_attr)
                     print_file(file, indent, "*%s%s = 0;\n", local_var_prefix, var->name);
                 print_file(file, indent, "NdrClientContextUnmarshall(\n");
                 print_file(file, indent + 1, "&__frame->_StubMsg,\n");
-                print_file(file, indent + 1, "(NDR_CCONTEXT *)%s%s,\n", local_var_prefix, var->name);
+                print_file(file, indent + 1, "(NDR_CCONTEXT *)%s%s%s,\n",
+                           pass == PASS_RETURN ? "&" : "", local_var_prefix, var->name);
                 print_file(file, indent + 1, "__frame->_Handle);\n");
             }
             else
@@ -4343,10 +4375,10 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const
                 ((tc == FC_SMVARRAY || tc == FC_LGVARRAY) && in_attr) ||
                 (tc == FC_CARRAY && !in_attr))
             {
-                if (type_array_is_decl_as_ptr(type) && type->details.array.ptr_tfsoff)
+                if (type_array_is_decl_as_ptr(type) && type_get_const_details(type)->array.ptr_tfsoff)
                 {
                     print_phase_function(file, indent, "Pointer", local_var_prefix, phase, var,
-                                         type->details.array.ptr_tfsoff);
+                                         type_get_const_details(type)->array.ptr_tfsoff);
                     break;
                 }
                 print_phase_function(file, indent, array_type, local_var_prefix, phase, var, start_offset);
@@ -4380,9 +4412,9 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const
             range_max = LIST_ENTRY(list_next(range_list, list_head(range_list)), const expr_t, entry);
 
             print_file(file, indent, "if ((%s%s < (", local_var_prefix, var->name);
-            write_type_decl(file, var->type, NULL);
+            write_declspec_decl(file, &var->declspec, NULL);
             fprintf(file, ")0x%x) || (%s%s > (", range_min->cval, local_var_prefix, var->name);
-            write_type_decl(file, var->type, NULL);
+            write_declspec_decl(file, &var->declspec, NULL);
             fprintf(file, ")0x%x))\n", range_max->cval);
             print_file(file, indent, "{\n");
             print_file(file, indent+1, "RpcRaiseException(RPC_S_INVALID_BOUND);\n");
@@ -4428,7 +4460,7 @@ static void write_remoting_arg(FILE *file, int indent, const var_t *func, const
     }
     case TGT_POINTER:
     {
-        const type_t *ref = type_pointer_get_ref(type);
+        const type_t *ref = type_pointer_get_ref_type(type);
         if (pointer_type == FC_RP) switch (typegen_detect_type(ref, NULL, TDT_ALL_TYPES))
         {
         case TGT_BASIC:
@@ -4549,14 +4581,14 @@ void write_remoting_arguments(FILE *file, int indent, const var_t *func, const c
     if (pass == PASS_RETURN)
     {
         write_remoting_arg( file, indent, func, local_var_prefix, pass, phase,
-                            type_function_get_retval(func->type) );
+                            type_function_get_retval(func->declspec.type) );
     }
     else
     {
         const var_t *var;
-        if (!type_get_function_args(func->type))
+        if (!type_function_get_args(func->declspec.type))
             return;
-        LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
+        LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), const var_t, entry )
             write_remoting_arg( file, indent, func, local_var_prefix, pass, phase, var );
     }
 }
@@ -4597,57 +4629,62 @@ void declare_stub_args( FILE *file, int indent, const var_t *func )
 {
     int in_attr, out_attr;
     int i = 0;
-    const var_t *var = type_function_get_retval(func->type);
+    const var_t *var = type_function_get_retval(func->declspec.type);
 
     /* declare return value */
-    if (!is_void(var->type))
+    if (!is_void(var->declspec.type))
     {
-        print_file(file, indent, "%s", "");
-        write_type_decl(file, var->type, var->name);
-        fprintf(file, ";\n");
+        if (is_context_handle(var->declspec.type))
+            print_file(file, indent, "NDR_SCONTEXT %s;\n", var->name);
+        else
+        {
+            print_file(file, indent, "%s", "");
+            write_declspec_decl(file, &var->declspec, var->name);
+            fprintf(file, ";\n");
+        }
     }
 
-    if (!type_get_function_args(func->type))
+    if (!type_function_get_args(func->declspec.type))
         return;
 
-    LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
+    LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), const var_t, entry )
     {
         in_attr = is_attr(var->attrs, ATTR_IN);
         out_attr = is_attr(var->attrs, ATTR_OUT);
         if (!out_attr && !in_attr)
             in_attr = 1;
 
-        if (is_context_handle(var->type))
+        if (is_context_handle(var->declspec.type))
             print_file(file, indent, "NDR_SCONTEXT %s;\n", var->name);
         else
         {
-            if (!in_attr && !is_conformant_array(var->type))
+            if (!in_attr && !is_conformant_array(var->declspec.type))
             {
-                type_t *type_to_print;
+                const decl_spec_t *declspec_to_print;
                 char name[16];
                 print_file(file, indent, "%s", "");
-                if (type_get_type(var->type) == TYPE_ARRAY &&
-                    !type_array_is_decl_as_ptr(var->type))
-                    type_to_print = var->type;
+                if (type_get_type(var->declspec.type) == TYPE_ARRAY &&
+                    !type_array_is_decl_as_ptr(var->declspec.type))
+                    declspec_to_print = &var->declspec;
                 else
-                    type_to_print = type_pointer_get_ref(var->type);
+                    declspec_to_print = type_pointer_get_ref(var->declspec.type);
                 sprintf(name, "_W%u", i++);
-                write_type_decl(file, type_to_print, name);
+                write_declspec_decl(file, declspec_to_print, name);
                 fprintf(file, ";\n");
             }
 
             print_file(file, indent, "%s", "");
-            write_type_decl_left(file, var->type);
+            write_declspec_decl_left(file, &var->declspec);
             fprintf(file, " ");
-            if (type_get_type(var->type) == TYPE_ARRAY &&
-                !type_array_is_decl_as_ptr(var->type)) {
+            if (type_get_type(var->declspec.type) == TYPE_ARRAY &&
+                !type_array_is_decl_as_ptr(var->declspec.type)) {
                 fprintf(file, "(*%s)", var->name);
             } else
                 fprintf(file, "%s", var->name);
-            write_type_right(file, var->type, FALSE);
+            write_type_right(file, var->declspec.type, FALSE);
             fprintf(file, ";\n");
 
-            if (decl_indirect(var->type))
+            if (decl_indirect(var->declspec.type))
                 print_file(file, indent, "void *_p_%s;\n", var->name);
         }
     }
@@ -4661,10 +4698,10 @@ void assign_stub_out_args( FILE *file, int indent, const var_t *func, const char
     const var_t *var;
     type_t *ref;
 
-    if (!type_get_function_args(func->type))
+    if (!type_function_get_args(func->declspec.type))
         return;
 
-    LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
+    LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), const var_t, entry )
     {
         in_attr = is_attr(var->attrs, ATTR_IN);
         out_attr = is_attr(var->attrs, ATTR_OUT);
@@ -4675,7 +4712,7 @@ void assign_stub_out_args( FILE *file, int indent, const var_t *func, const char
         {
             print_file(file, indent, "%s%s", local_var_prefix, var->name);
 
-            switch (typegen_detect_type(var->type, var->attrs, TDT_IGNORE_STRINGS))
+            switch (typegen_detect_type(var->declspec.type, var->attrs, TDT_IGNORE_STRINGS))
             {
             case TGT_CTXT_HANDLE_POINTER:
                 fprintf(file, " = NdrContextHandleInitialize(\n");
@@ -4684,15 +4721,15 @@ void assign_stub_out_args( FILE *file, int indent, const var_t *func, const char
                            var->typestring_offset);
                 break;
             case TGT_ARRAY:
-                if (type_array_has_conformance(var->type))
+                if (type_array_has_conformance(var->declspec.type))
                 {
                     unsigned int size;
                     type_t *type;
 
                     fprintf(file, " = NdrAllocate(&__frame->_StubMsg, ");
-                    for (type = var->type;
+                    for (type = var->declspec.type;
                          is_array(type) && type_array_has_conformance(type);
-                         type = type_array_get_element(type))
+                         type = type_array_get_element_type(type))
                     {
                         write_expr(file, type_array_get_conformance(type), TRUE,
                                    TRUE, NULL, NULL, local_var_prefix);
@@ -4702,9 +4739,9 @@ void assign_stub_out_args( FILE *file, int indent, const var_t *func, const char
                     fprintf(file, "%u);\n", size);
 
                     print_file(file, indent, "memset(%s%s, 0, ", local_var_prefix, var->name);
-                    for (type = var->type;
+                    for (type = var->declspec.type;
                          is_array(type) && type_array_has_conformance(type);
-                         type = type_array_get_element(type))
+                         type = type_array_get_element_type(type))
                     {
                         write_expr(file, type_array_get_conformance(type), TRUE,
                                    TRUE, NULL, NULL, local_var_prefix);
@@ -4718,7 +4755,7 @@ void assign_stub_out_args( FILE *file, int indent, const var_t *func, const char
                 break;
             case TGT_POINTER:
                 fprintf(file, " = &%s_W%u;\n", local_var_prefix, i);
-                ref = type_pointer_get_ref(var->type);
+                ref = type_pointer_get_ref_type(var->declspec.type);
                 switch (typegen_detect_type(ref, var->attrs, TDT_IGNORE_STRINGS))
                 {
                 case TGT_BASIC:
@@ -4738,7 +4775,7 @@ void assign_stub_out_args( FILE *file, int indent, const var_t *func, const char
                         print_file(file, indent, "%s_W%u = 0;\n", local_var_prefix, i);
                         break;
                     }
-                    ref = type_array_get_element(ref);
+                    ref = type_array_get_element_type(ref);
                     /* fall through */
                 case TGT_STRUCT:
                 case TGT_UNION:
@@ -4771,14 +4808,14 @@ void write_func_param_struct( FILE *file, const type_t *iface, const type_t *fun
                               const char *var_decl, int add_retval )
 {
     var_t *retval = type_function_get_retval( func );
-    const var_list_t *args = type_get_function_args( func );
+    const var_list_t *args = type_function_get_args( func );
     const var_t *arg;
     int needs_packing;
     unsigned int align = 0;
 
     if (args)
         LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry )
-            if (!is_array( arg->type )) type_memsize_and_alignment( arg->type, &align );
+            if (!is_array( arg->declspec.type )) type_memsize_and_alignment( arg->declspec.type, &align );
 
     needs_packing = (align > pointer_size);
 
@@ -4790,26 +4827,26 @@ void write_func_param_struct( FILE *file, const type_t *iface, const type_t *fun
     if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry )
     {
         print_file(file, 2, "%s", "");
-        write_type_left( file, (type_t *)arg->type, NAME_DEFAULT, TRUE );
-        if (needs_space_after( arg->type )) fputc( ' ', file );
-        if (is_array( arg->type ) && !type_array_is_decl_as_ptr( arg->type )) fputc( '*', file );
+        write_declspec_left( file, &arg->declspec, NAME_DEFAULT, TRUE );
+        if (needs_space_after( arg->declspec.type )) fputc( ' ', file );
+        if (is_array( arg->declspec.type ) && !type_array_is_decl_as_ptr( arg->declspec.type )) fputc( '*', file );
 
         /* FIXME: should check for large args being passed by pointer */
         align = 0;
-        if (is_array( arg->type ) || is_ptr( arg->type )) align = pointer_size;
-        else type_memsize_and_alignment( arg->type, &align );
+        if (is_array( arg->declspec.type ) || is_ptr( arg->declspec.type )) align = pointer_size;
+        else type_memsize_and_alignment( arg->declspec.type, &align );
 
         if (align >= pointer_size)
             fprintf( file, "%s;\n", arg->name );
         else
             fprintf( file, "%s DECLSPEC_ALIGN(%u);\n", arg->name, pointer_size );
     }
-    if (add_retval && !is_void( retval->type ))
+    if (add_retval && !is_void( retval->declspec.type ))
     {
         print_file(file, 2, "%s", "");
-        write_type_decl( file, retval->type, retval->name );
-        if (is_array( retval->type ) || is_ptr( retval->type ) ||
-            type_memsize( retval->type ) == pointer_size)
+        write_declspec_decl( file, &retval->declspec, retval->name );
+        if (is_array( retval->declspec.type ) || is_ptr( retval->declspec.type ) ||
+            type_memsize( retval->declspec.type ) == pointer_size)
             fprintf( file, ";\n" );
         else
             fprintf( file, " DECLSPEC_ALIGN(%u);\n", pointer_size );
@@ -4821,7 +4858,7 @@ void write_func_param_struct( FILE *file, const type_t *iface, const type_t *fun
 
 void write_pointer_checks( FILE *file, int indent, const var_t *func )
 {
-    const var_list_t *args = type_get_function_args( func->type );
+    const var_list_t *args = type_function_get_args( func->declspec.type );
     const var_t *var;
 
     if (!args) return;
@@ -4854,10 +4891,11 @@ int write_expr_eval_routines(FILE *file, const char *iface)
         }
         else
         {
+            decl_spec_t declspec;
             print_file(file, 1, "%s", "");
-            write_type_left(file, (type_t *)eval->cont_type, NAME_DEFAULT, TRUE);
+            write_declspec_left(file, init_declspec(&declspec, (type_t*)eval->cont_type), NAME_DEFAULT, TRUE);
             fprintf(file, " *%s = (", var_name);
-            write_type_left(file, (type_t *)eval->cont_type, NAME_DEFAULT, TRUE);
+            write_declspec_left(file, init_declspec(&declspec, (type_t*)eval->cont_type), NAME_DEFAULT, TRUE);
             fprintf(file, " *)(pStubMsg->StackTop - %u);\n", eval->baseoff);
         }
         print_file(file, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */
@@ -4951,9 +4989,10 @@ error:
 void write_client_call_routine( FILE *file, const type_t *iface, const var_t *func,
                                 const char *prefix, unsigned int proc_offset )
 {
-    type_t *rettype = type_function_get_rettype( func->type );
+    const decl_spec_t *retdeclspec = type_function_get_retdeclspec(func->declspec.type);
+    type_t *rettype = retdeclspec->type;
     int has_ret = !is_void( rettype );
-    const var_list_t *args = type_get_function_args( func->type );
+    const var_list_t *args = type_function_get_args( func->declspec.type );
     const var_t *arg;
     int len, needs_params = 0;
 
@@ -4964,7 +5003,7 @@ void write_client_call_routine( FILE *file, const type_t *iface, const var_t *fu
     if (needs_params)
     {
         if (has_ret) print_file( file, 1, "%s", "CLIENT_CALL_RETURN _RetVal;\n" );
-        write_func_param_struct( file, iface, func->type, "__params", FALSE );
+        write_func_param_struct( file, iface, func->declspec.type, "__params", FALSE );
         if (is_object( iface )) print_file( file, 1, "__params.This = This;\n" );
         if (args)
             LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry )
@@ -5001,7 +5040,7 @@ void write_client_call_routine( FILE *file, const type_t *iface, const var_t *fu
     if (has_ret)
     {
         print_file( file, 1, "return (" );
-        write_type_decl_left(file, rettype);
+        write_declspec_decl_left(file, retdeclspec);
         fprintf( file, ")%s;\n", pointer_size == 8 ? "_RetVal.Simple" : "*(LONG_PTR *)&_RetVal" );
     }
     print_file( file, 0, "}\n\n");
@@ -5029,7 +5068,7 @@ void write_exceptions( FILE *file )
     fprintf( file, "    EXCEPTION_REGISTRATION_RECORD frame; \\\n");
     fprintf( file, "    __filter_func                 filter; \\\n");
     fprintf( file, "    __finally_func                finally; \\\n");
-    fprintf( file, "    sigjmp_buf                    jmp; \\\n");
+    fprintf( file, "    __wine_jmp_buf                jmp; \\\n");
     fprintf( file, "    DWORD                         code; \\\n");
     fprintf( file, "    unsigned char                 abnormal_termination; \\\n");
     fprintf( file, "    unsigned char                 filter_level; \\\n");
@@ -5049,13 +5088,13 @@ void write_exceptions( FILE *file )
     fprintf( file, "        __wine_pop_frame( &exc_frame->frame );\n");
     fprintf( file, "    }\n");
     fprintf( file, "    exc_frame->filter_level = 0;\n");
-    fprintf( file, "    siglongjmp( exc_frame->jmp, 1 );\n");
+    fprintf( file, "    __wine_longjmp( &exc_frame->jmp, 1 );\n");
     fprintf( file, "}\n");
     fprintf( file, "\n");
-    fprintf( file, "static DWORD __widl_exception_handler( EXCEPTION_RECORD *record,\n");
-    fprintf( file, "                                       EXCEPTION_REGISTRATION_RECORD *frame,\n");
-    fprintf( file, "                                       CONTEXT *context,\n");
-    fprintf( file, "                                       EXCEPTION_REGISTRATION_RECORD **pdispatcher )\n");
+    fprintf( file, "static DWORD __cdecl __widl_exception_handler( EXCEPTION_RECORD *record,\n");
+    fprintf( file, "                                               EXCEPTION_REGISTRATION_RECORD *frame,\n");
+    fprintf( file, "                                               CONTEXT *context,\n");
+    fprintf( file, "                                               EXCEPTION_REGISTRATION_RECORD **pdispatcher )\n");
     fprintf( file, "{\n");
     fprintf( file, "    struct __exception_frame *exc_frame = (struct __exception_frame *)frame;\n");
     fprintf( file, "\n");
@@ -5075,7 +5114,7 @@ void write_exceptions( FILE *file )
     fprintf( file, "}\n");
     fprintf( file, "\n");
     fprintf( file, "#define RpcTryExcept \\\n");
-    fprintf( file, "    if (!sigsetjmp( __frame->jmp, 0 )) \\\n");
+    fprintf( file, "    if (!__wine_setjmpex( &__frame->jmp, &__frame->frame )) \\\n");
     fprintf( file, "    { \\\n");
     fprintf( file, "        if (!__frame->finally_level) \\\n" );
     fprintf( file, "            __wine_push_frame( &__frame->frame ); \\\n");
diff --git a/mingw-w64-tools/widl/src/typelib.c b/mingw-w64-tools/widl/src/typelib.c
index 9b1de2c8..2c2b1276 100644
--- a/mingw-w64-tools/widl/src/typelib.c
+++ b/mingw-w64-tools/widl/src/typelib.c
@@ -97,9 +97,9 @@ static unsigned short builtin_vt(const type_t *t)
   {
     const type_t *elem_type;
     if (is_array(t))
-      elem_type = type_array_get_element(t);
+      elem_type = type_array_get_element_type(t);
     else
-      elem_type = type_pointer_get_ref(t);
+      elem_type = type_pointer_get_ref_type(t);
     if (type_get_type(elem_type) == TYPE_BASIC)
     {
       switch (type_basic_get_type(elem_type))
@@ -129,7 +129,8 @@ unsigned short get_type_vt(type_t *t)
     if (vt) return vt;
   }
 
-  if (type_is_alias(t) && is_attr(t->attrs, ATTR_PUBLIC))
+  if (type_is_alias(t) &&
+      (is_attr(t->attrs, ATTR_PUBLIC) || is_attr(t->attrs, ATTR_WIREMARSHAL)))
     return VT_USERDEFINED;
 
   switch (type_get_type(t)) {
@@ -169,7 +170,7 @@ unsigned short get_type_vt(type_t *t)
       else
         return VT_I8;
     case TYPE_BASIC_INT3264:
-      if (typelib_kind == SYS_WIN64)
+      if (pointer_size == 8)
       {
         if (type_basic_get_sign(t) > 0)
           return VT_UI8;
@@ -198,7 +199,7 @@ unsigned short get_type_vt(type_t *t)
   case TYPE_ARRAY:
     if (type_array_is_decl_as_ptr(t))
     {
-      if (match(type_array_get_element(t)->name, "SAFEARRAY"))
+      if (match(type_array_get_element_type(t)->name, "SAFEARRAY"))
         return VT_SAFEARRAY;
       return VT_PTR;
     }
diff --git a/mingw-w64-tools/widl/src/typetree.c b/mingw-w64-tools/widl/src/typetree.c
index b93806be..488f7a49 100644
--- a/mingw-w64-tools/widl/src/typetree.c
+++ b/mingw-w64-tools/widl/src/typetree.c
@@ -30,12 +30,16 @@
 #include "typetree.h"
 #include "header.h"
 
-type_t *duptype(type_t *t, int dupname)
+/* this function is only used in declare_var in parser.y, see FIXME note */
+type_t *dup_pointer_type(type_t *t)
 {
-  type_t *d = alloc_type();
+  type_t *d;
 
+  assert(is_ptr(t) && t->details.pointer.def_fc != FC_RP);
+
+  d = alloc_type();
   *d = *t;
-  if (dupname && t->name)
+  if (t->name)
     d->name = xstrdup(t->name);
 
   return d;
@@ -49,7 +53,6 @@ type_t *make_type(enum type_type type)
     t->type_type = type;
     t->attrs = NULL;
     t->c_name = NULL;
-    t->orig = NULL;
     memset(&t->details, 0, sizeof(t->details));
     t->typestring_offset = 0;
     t->ptrdesc = 0;
@@ -137,7 +140,7 @@ type_t *type_new_function(var_list_t *args)
     if (args)
     {
         arg = LIST_ENTRY(list_head(args), var_t, entry);
-        if (list_count(args) == 1 && !arg->name && arg->type && type_get_type(arg->type) == TYPE_VOID)
+        if (list_count(args) == 1 && !arg->name && arg->declspec.type && type_get_type(arg->declspec.type) == TYPE_VOID)
         {
             list_remove(&arg->entry);
             free(arg);
@@ -147,7 +150,7 @@ type_t *type_new_function(var_list_t *args)
     }
     if (args) LIST_FOR_EACH_ENTRY(arg, args, var_t, entry)
     {
-        if (arg->type && type_get_type(arg->type) == TYPE_VOID)
+        if (arg->declspec.type && type_get_type(arg->declspec.type) == TYPE_VOID)
             error_loc("argument '%s' has void type\n", arg->name);
         if (!arg->name)
         {
@@ -178,34 +181,28 @@ type_t *type_new_function(var_list_t *args)
     return t;
 }
 
-type_t *type_new_pointer(unsigned char pointer_default, type_t *ref, attr_list_t *attrs)
+type_t *type_new_pointer(unsigned char pointer_default, type_t *ref)
 {
     type_t *t = make_type(TYPE_POINTER);
     t->details.pointer.def_fc = pointer_default;
-    t->details.pointer.ref = ref;
-    t->attrs = attrs;
+    t->details.pointer.ref.type = ref;
     return t;
 }
 
-type_t *type_new_alias(type_t *t, const char *name)
+type_t *type_new_alias(const decl_spec_t *ds, const char *name)
 {
-    type_t *a = duptype(t, 0);
-
+    type_t *a = make_type(ds->type->type_type);
     a->name = xstrdup(name);
     a->attrs = NULL;
-    a->orig = t;
+    a->details.alias.aliasee = *ds;
     a->is_alias = TRUE;
-    /* for pointer types */
-    a->details = t->details;
-    init_loc_info(&a->loc_info);
-
     return a;
 }
 
 type_t *type_new_module(char *name)
 {
     type_t *type = get_type(TYPE_MODULE, name, NULL, 0);
-    if (type->type_type != TYPE_MODULE || type->defined)
+    if (type->type_type != TYPE_MODULE || type_is_defined(type))
         error_loc("%s: redefinition error; original definition was at %s:%d\n",
                   type->name, type->loc_info.input_name, type->loc_info.line_number);
     type->name = name;
@@ -215,7 +212,7 @@ type_t *type_new_module(char *name)
 type_t *type_new_coclass(char *name)
 {
     type_t *type = get_type(TYPE_COCLASS, name, NULL, 0);
-    if (type->type_type != TYPE_COCLASS || type->defined)
+    if (type->type_type != TYPE_COCLASS || type_is_defined(type))
         error_loc("%s: redefinition error; original definition was at %s:%d\n",
                   type->name, type->loc_info.input_name, type->loc_info.line_number);
     type->name = name;
@@ -223,7 +220,7 @@ type_t *type_new_coclass(char *name)
 }
 
 
-type_t *type_new_array(const char *name, type_t *element, int declptr,
+type_t *type_new_array(const char *name, const decl_spec_t *element, int declptr,
                        unsigned int dim, expr_t *size_is, expr_t *length_is,
                        unsigned char ptr_default_fc)
 {
@@ -235,7 +232,9 @@ type_t *type_new_array(const char *name, type_t *element, int declptr,
         t->details.array.size_is = size_is;
     else
         t->details.array.dim = dim;
-    t->details.array.elem = element;
+    if (element) {
+        t->details.array.elem = *element;
+    }
     t->details.array.ptr_def_fc = ptr_default_fc;
     return t;
 }
@@ -273,80 +272,99 @@ type_t *type_new_void(void)
 
 type_t *type_new_enum(const char *name, struct namespace *namespace, int defined, var_list_t *enums)
 {
-    type_t *tag_type = name ? find_type(name, namespace, tsENUM) : NULL;
-    type_t *t = make_type(TYPE_ENUM);
-    t->name = name;
-    t->namespace = namespace;
-
-    if (tag_type && tag_type->details.enumeration)
-        t->details.enumeration = tag_type->details.enumeration;
-    else if (defined)
+    type_t *t = NULL;
+
+    if (name)
+        t = find_type(name, namespace, tsENUM);
+
+    if (!t)
     {
-        t->details.enumeration = xmalloc(sizeof(*t->details.enumeration));
-        t->details.enumeration->enums = enums;
-        t->defined = TRUE;
+        t = make_type(TYPE_ENUM);
+        t->name = name;
+        t->namespace = namespace;
+        if (name)
+            reg_type(t, name, namespace, tsENUM);
     }
 
-    if (name)
+    if (!type_is_defined(t))
     {
         if (defined)
-            reg_type(t, name, namespace, tsENUM);
+        {
+            t->details.enumeration = xmalloc(sizeof(*t->details.enumeration));
+            t->details.enumeration->enums = enums;
+            t->defined = TRUE;
+        }
         else
+        {
             add_incomplete(t);
+        }
     }
+
     return t;
 }
 
 type_t *type_new_struct(char *name, struct namespace *namespace, int defined, var_list_t *fields)
 {
-    type_t *tag_type = name ? find_type(name, namespace, tsSTRUCT) : NULL;
-    type_t *t;
-
-    /* avoid creating duplicate typelib type entries */
-    if (tag_type && do_typelib) return tag_type;
+    type_t *t = NULL;
 
-    t = make_type(TYPE_STRUCT);
-    t->name = name;
-    t->namespace = namespace;
+    if (name)
+        t = find_type(name, namespace, tsSTRUCT);
 
-    if (tag_type && tag_type->details.structure)
-        t->details.structure = tag_type->details.structure;
-    else if (defined)
+    if (!t)
     {
-        t->details.structure = xmalloc(sizeof(*t->details.structure));
-        t->details.structure->fields = fields;
-        t->defined = TRUE;
+        t = make_type(TYPE_STRUCT);
+        t->name = name;
+        t->namespace = namespace;
+        if (name)
+            reg_type(t, name, namespace, tsSTRUCT);
     }
-    if (name)
+
+    if (!type_is_defined(t))
     {
         if (defined)
-            reg_type(t, name, namespace, tsSTRUCT);
+        {
+            t->details.structure = xmalloc(sizeof(*t->details.structure));
+            t->details.structure->fields = fields;
+            t->defined = TRUE;
+        }
         else
+        {
             add_incomplete(t);
+        }
     }
+
     return t;
 }
 
 type_t *type_new_nonencapsulated_union(const char *name, int defined, var_list_t *fields)
 {
-    type_t *tag_type = name ? find_type(name, NULL, tsUNION) : NULL;
-    type_t *t = make_type(TYPE_UNION);
-    t->name = name;
-    if (tag_type && tag_type->details.structure)
-        t->details.structure = tag_type->details.structure;
-    else if (defined)
+    type_t *t = NULL;
+
+    if (name)
+        t = find_type(name, NULL, tsUNION);
+
+    if (!t)
     {
-        t->details.structure = xmalloc(sizeof(*t->details.structure));
-        t->details.structure->fields = fields;
-        t->defined = TRUE;
+        t = make_type(TYPE_UNION);
+        t->name = name;
+        if (name)
+            reg_type(t, name, NULL, tsUNION);
     }
-    if (name)
+
+    if (!type_is_defined(t))
     {
         if (defined)
-            reg_type(t, name, NULL, tsUNION);
+        {
+            t->details.structure = xmalloc(sizeof(*t->details.structure));
+            t->details.structure->fields = fields;
+            t->defined = TRUE;
+        }
         else
+        {
             add_incomplete(t);
+        }
     }
+
     return t;
 }
 
@@ -354,7 +372,7 @@ type_t *type_new_encapsulated_union(char *name, var_t *switch_field, var_t *unio
 {
     type_t *t = get_type(TYPE_ENCAPSULATED_UNION, name, NULL, tsUNION);
     if (!union_field) union_field = make_var( xstrdup("tagged_union") );
-    union_field->type = type_new_nonencapsulated_union(NULL, TRUE, cases);
+    union_field->declspec.type = type_new_nonencapsulated_union(NULL, TRUE, cases);
     t->details.structure = xmalloc(sizeof(*t->details.structure));
     t->details.structure->fields = append_var( NULL, switch_field );
     t->details.structure->fields = append_var( t->details.structure->fields, union_field );
@@ -430,7 +448,7 @@ static int compute_method_indexes(type_t *iface)
     {
         var_t *func = stmt->u.var;
         if (!is_callas(func->attrs))
-            func->type->details.function->idx = idx++;
+            func->declspec.type->details.function->idx = idx++;
     }
 
     return idx;
@@ -438,6 +456,7 @@ static int compute_method_indexes(type_t *iface)
 
 void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts)
 {
+    assert(type_get_type_detect_alias(iface) == TYPE_INTERFACE);
     iface->details.iface = xmalloc(sizeof(*iface->details.iface));
     iface->details.iface->disp_props = NULL;
     iface->details.iface->disp_methods = NULL;
@@ -451,6 +470,7 @@ void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stm
 
 void type_dispinterface_define(type_t *iface, var_list_t *props, var_list_t *methods)
 {
+    assert(type_get_type_detect_alias(iface) == TYPE_INTERFACE);
     iface->details.iface = xmalloc(sizeof(*iface->details.iface));
     iface->details.iface->disp_props = props;
     iface->details.iface->disp_methods = methods;
@@ -465,6 +485,7 @@ void type_dispinterface_define(type_t *iface, var_list_t *props, var_list_t *met
 
 void type_dispinterface_define_from_iface(type_t *dispiface, type_t *iface)
 {
+    assert(type_get_type_detect_alias(iface) == TYPE_INTERFACE);
     dispiface->details.iface = xmalloc(sizeof(*dispiface->details.iface));
     dispiface->details.iface->disp_props = NULL;
     dispiface->details.iface->disp_methods = NULL;
@@ -479,6 +500,7 @@ void type_dispinterface_define_from_iface(type_t *dispiface, type_t *iface)
 
 void type_module_define(type_t *module, statement_list_t *stmts)
 {
+    assert(type_get_type_detect_alias(module) == TYPE_MODULE);
     if (module->details.module) error_loc("multiple definition error\n");
     module->details.module = xmalloc(sizeof(*module->details.module));
     module->details.module->stmts = stmts;
@@ -487,6 +509,7 @@ void type_module_define(type_t *module, statement_list_t *stmts)
 
 type_t *type_coclass_define(type_t *coclass, ifref_list_t *ifaces)
 {
+    assert(type_get_type_detect_alias(coclass) == TYPE_COCLASS);
     coclass->details.coclass.ifaces = ifaces;
     coclass->defined = TRUE;
     return coclass;
diff --git a/mingw-w64-tools/widl/src/typetree.h b/mingw-w64-tools/widl/src/typetree.h
index fc134cd5..96fcae8d 100644
--- a/mingw-w64-tools/widl/src/typetree.h
+++ b/mingw-w64-tools/widl/src/typetree.h
@@ -30,10 +30,10 @@ enum name_type {
 };
 
 type_t *type_new_function(var_list_t *args);
-type_t *type_new_pointer(unsigned char pointer_default, type_t *ref, attr_list_t *attrs);
-type_t *type_new_alias(type_t *t, const char *name);
+type_t *type_new_pointer(unsigned char pointer_default, type_t *ref);
+type_t *type_new_alias(const decl_spec_t *aliasee, const char *name);
 type_t *type_new_module(char *name);
-type_t *type_new_array(const char *name, type_t *element, int declptr,
+type_t *type_new_array(const char* name, const decl_spec_t *element, int declptr,
                        unsigned int dim, expr_t *size_is, expr_t *length_is,
                        unsigned char ptr_default_fc);
 type_t *type_new_basic(enum type_basic_type basic_type);
@@ -53,14 +53,38 @@ type_t *type_coclass_define(type_t *coclass, ifref_list_t *ifaces);
 int type_is_equal(const type_t *type1, const type_t *type2);
 const char *type_get_name(const type_t *type, enum name_type name_type);
 
-/* FIXME: shouldn't need to export this */
-type_t *duptype(type_t *t, int dupname);
+/* copy pointer type to deal with need for duplicate typeformat strings */
+type_t *dup_pointer_type(type_t *t);
+
+#define STATEMENTS_FOR_EACH_FUNC(stmt, stmts) \
+  if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, statement_t, entry ) \
+    if (stmt->type == STMT_DECLARATION && stmt->u.var->declspec.stgclass == STG_NONE && \
+        type_get_type_detect_alias(stmt->u.var->declspec.type) == TYPE_FUNCTION)
+
+static inline enum type_type type_get_type_detect_alias(const type_t *type)
+{
+    if (type->is_alias)
+        return TYPE_ALIAS;
+    return type->type_type;
+}
+
+static inline int statements_has_func(const statement_list_t *stmts)
+{
+  const statement_t *stmt;
+  int has_func = 0;
+  STATEMENTS_FOR_EACH_FUNC(stmt, stmts)
+  {
+    has_func = 1;
+    break;
+  }
+  return has_func;
+}
 
 /* un-alias the type until finding the non-alias type */
 static inline type_t *type_get_real_type(const type_t *type)
 {
     if (type->is_alias)
-        return type_get_real_type(type->orig);
+        return type_get_real_type(type->details.alias.aliasee.type);
     else
         return (type_t *)type;
 }
@@ -105,9 +129,14 @@ static inline var_t *type_function_get_retval(const type_t *type)
     return type->details.function->retval;
 }
 
+static inline const decl_spec_t *type_function_get_retdeclspec(const type_t *type)
+{
+    return &type_function_get_retval(type)->declspec;
+}
+
 static inline type_t *type_function_get_rettype(const type_t *type)
 {
-    return type_function_get_retval(type)->type;
+    return type_function_get_retdeclspec(type)->type;
 }
 
 static inline var_list_t *type_enum_get_values(const type_t *type)
@@ -142,7 +171,7 @@ static inline var_list_t *type_union_get_cases(const type_t *type)
     if (type_type == TYPE_ENCAPSULATED_UNION)
     {
         const var_t *uv = LIST_ENTRY(list_tail(type->details.structure->fields), const var_t, entry);
-        return uv->type->details.structure->fields;
+        return uv->declspec.type->details.structure->fields;
     }
     else
         return type->details.structure->fields;
@@ -250,11 +279,16 @@ static inline expr_t *type_array_get_variance(const type_t *type)
     return type->details.array.length_is;
 }
 
-static inline type_t *type_array_get_element(const type_t *type)
+static inline const decl_spec_t *type_array_get_element(const type_t *type)
 {
     type = type_get_real_type(type);
     assert(type_get_type(type) == TYPE_ARRAY);
-    return type->details.array.elem;
+    return &type->details.array.elem;
+}
+
+static inline type_t *type_array_get_element_type(const type_t *type)
+{
+    return type_array_get_element(type)->type;
 }
 
 static inline int type_array_is_decl_as_ptr(const type_t *type)
@@ -276,10 +310,15 @@ static inline int type_is_alias(const type_t *type)
     return type->is_alias;
 }
 
-static inline type_t *type_alias_get_aliasee(const type_t *type)
+static inline const decl_spec_t *type_alias_get_aliasee(const type_t *type)
 {
     assert(type_is_alias(type));
-    return type->orig;
+    return &type->details.alias.aliasee;
+}
+
+static inline type_t *type_alias_get_aliasee_type(const type_t *type)
+{
+    return type_alias_get_aliasee(type)->type;
 }
 
 static inline ifref_list_t *type_coclass_get_ifaces(const type_t *type)
@@ -289,11 +328,16 @@ static inline ifref_list_t *type_coclass_get_ifaces(const type_t *type)
     return type->details.coclass.ifaces;
 }
 
-static inline type_t *type_pointer_get_ref(const type_t *type)
+static inline const decl_spec_t *type_pointer_get_ref(const type_t *type)
 {
     type = type_get_real_type(type);
     assert(type_get_type(type) == TYPE_POINTER);
-    return type->details.pointer.ref;
+    return &type->details.pointer.ref;
+}
+
+static inline type_t *type_pointer_get_ref_type(const type_t *type)
+{
+    return type_pointer_get_ref(type)->type;
 }
 
 static inline unsigned char type_pointer_get_default_fc(const type_t *type)
@@ -317,4 +361,54 @@ static inline const expr_t *type_bitfield_get_bits(const type_t *type)
     return type->details.bitfield.bits;
 }
 
+/* gets pointer to details_t union with the assumption the caller wants to write to it
+ * so assert if we're actually dealing with an alias and writing to the details would
+ * overwrite the alias_details
+ */
+static inline details_t *type_get_details(type_t* type)
+{
+    assert(!type_is_alias(type));
+    return &type->details;
+}
+
+/* const overload of type_get_details */
+
+static inline const details_t *type_get_const_details(const type_t* type)
+{
+    assert(!type_is_alias(type));
+    return &type->details;
+}
+
+static inline int type_is_pointerish(const type_t *type)
+{
+    type = type_get_real_type(type);
+    return type_get_type(type) == TYPE_ARRAY || type_get_type(type) == TYPE_POINTER;
+}
+
+static inline type_t * type_get_pointer_chain_tail(const type_t *type)
+{
+    type_t *pointee = NULL;
+    type_t *pointer = type_get_real_type(type);
+
+    if (type_get_type(pointer) == TYPE_ARRAY)
+    {
+        pointee = type_array_get_element_type(pointer);
+    }
+    else if (type_get_type(pointer) == TYPE_POINTER)
+    {
+        pointee = type_pointer_get_ref_type(pointer);
+    }
+    else
+    {
+        assert(FALSE);
+    }
+
+    if (type_is_pointerish(pointee))
+    {
+        return type_get_pointer_chain_tail(pointee);
+    }
+
+    return pointee;
+}
+
 #endif /* WIDL_TYPE_TREE_H */
diff --git a/mingw-w64-tools/widl/src/widl.c b/mingw-w64-tools/widl/src/widl.c
index 1af42509..8542e518 100644
--- a/mingw-w64-tools/widl/src/widl.c
+++ b/mingw-w64-tools/widl/src/widl.c
@@ -44,11 +44,6 @@
 #include "header.h"
 #include "pathtools.h"
 
-/* future options to reserve characters for: */
-/* A = ACF input filename */
-/* J = do not search standard include path */
-/* w = select win16/win32 output (?) */
-
 static const char usage[] =
 "Usage: widl [options...] infile.idl\n"
 "   or: widl [options...] --dlldata-only name1 [name2...]\n"
@@ -64,7 +59,7 @@ static const char usage[] =
 "   -H file            Name of header file (default is infile.h)\n"
 "   -I path            Set include search dir to path (multiple -I allowed)\n"
 "   --local-stubs=file Write empty stubs for call_as/local methods to file\n"
-"   -m32, -m64         Set the kind of typelib to build (Win32 or Win64)\n"
+"   -m32, -m64         Set the target architecture (Win32 or Win64)\n"
 "   -N                 Do not preprocess input\n"
 "   --oldnames         Use old naming conventions\n"
 "   -o, --output=NAME  Set the output file name\n"
@@ -82,8 +77,7 @@ static const char usage[] =
 "   -u                 Generate interface identifiers file\n"
 "   -V                 Print version and exit\n"
 "   -W                 Enable pedantic warnings\n"
-"   --win32            Only generate 32-bit code\n"
-"   --win64            Only generate 64-bit code\n"
+"   --win32, --win64   Set the target architecture (Win32 or Win64)\n"
 "   --win32-align n    Set win32 structure alignment to 'n'\n"
 "   --win64-align n    Set win64 structure alignment to 'n'\n"
 "Debug level 'n' is a bitmask with following meaning:\n"
@@ -98,6 +92,20 @@ static const char usage[] =
 static const char version_string[] = "Wine IDL Compiler version " PACKAGE_VERSION "\n"
 			"Copyright 2002 Ove Kaaven\n";
 
+#ifdef __i386__
+enum target_cpu target_cpu = CPU_x86;
+#elif defined(__x86_64__)
+enum target_cpu target_cpu = CPU_x86_64;
+#elif defined(__powerpc__)
+enum target_cpu target_cpu = CPU_POWERPC;
+#elif defined(__arm__)
+enum target_cpu target_cpu = CPU_ARM;
+#elif defined(__aarch64__)
+enum target_cpu target_cpu = CPU_ARM64;
+#else
+#error Unsupported CPU
+#endif
+
 int debuglevel = DEBUGLEVEL_NONE;
 int parser_debug, yy_flex_debug;
 
@@ -114,8 +122,6 @@ int do_idfile = 0;
 int do_dlldata = 0;
 static int no_preprocess = 0;
 int old_names = 0;
-int do_win32 = 1;
-int do_win64 = 1;
 int win32_packing = 8;
 int win64_packing = 8;
 int winrt_mode = 0;
@@ -148,7 +154,6 @@ int line_number = 1;
 static FILE *idfile;
 
 unsigned int pointer_size = 0;
-syskind_t typelib_kind = sizeof(void*) == 8 ? SYS_WIN64 : SYS_WIN32;
 
 time_t now;
 
@@ -188,6 +193,7 @@ static const struct option long_options[] = {
     { "prefix-client", 1, NULL, PREFIX_CLIENT_OPTION },
     { "prefix-server", 1, NULL, PREFIX_SERVER_OPTION },
     { "robust", 0, NULL, ROBUST_OPTION },
+    { "target", 0, NULL, 'b' },
     { "winrt", 0, NULL, RT_OPTION },
     { "win32", 0, NULL, WIN32_OPTION },
     { "win64", 0, NULL, WIN64_OPTION },
@@ -269,20 +275,25 @@ static void set_target( const char *target )
 {
     static const struct
     {
-        const char *name;
-        syskind_t   kind;
+        const char     *name;
+        enum target_cpu cpu;
     } cpu_names[] =
     {
-        { "i386",    SYS_WIN32 },
-        { "i486",    SYS_WIN32 },
-        { "i586",    SYS_WIN32 },
-        { "i686",    SYS_WIN32 },
-        { "i786",    SYS_WIN32 },
-        { "amd64",   SYS_WIN64 },
-        { "x86_64",  SYS_WIN64 },
-        { "powerpc", SYS_WIN32 },
-        { "arm",     SYS_WIN32 },
-        { "aarch64", SYS_WIN64 }
+        { "i386",    CPU_x86 },
+        { "i486",    CPU_x86 },
+        { "i586",    CPU_x86 },
+        { "i686",    CPU_x86 },
+        { "i786",    CPU_x86 },
+        { "amd64",   CPU_x86_64 },
+        { "x86_64",  CPU_x86_64 },
+        { "powerpc", CPU_POWERPC },
+        { "arm",     CPU_ARM },
+        { "armv5",   CPU_ARM },
+        { "armv6",   CPU_ARM },
+        { "armv7",   CPU_ARM },
+        { "armv7a",  CPU_ARM },
+        { "arm64",   CPU_ARM64 },
+        { "aarch64", CPU_ARM64 },
     };
 
     unsigned int i;
@@ -296,7 +307,7 @@ static void set_target( const char *target )
     {
         if (!strcmp( cpu_names[i].name, spec ))
         {
-            typelib_kind = cpu_names[i].kind;
+            target_cpu = cpu_names[i].cpu;
             free( spec );
             return;
         }
@@ -484,6 +495,7 @@ static void write_id_data_stmts(const statement_list_t *stmts)
         uuid = get_attrp(type->attrs, ATTR_UUID);
         write_id_guid(idfile, "IID", is_attr(type->attrs, ATTR_DISPINTERFACE) ? "DIID" : "IID",
                    type->name, uuid);
+        assert(type_get_type_detect_alias(type) == TYPE_INTERFACE);
         if (type->details.iface->async_iface)
         {
           uuid = get_attrp(type->details.iface->async_iface->attrs, ATTR_UUID);
@@ -606,12 +618,10 @@ int main(int argc,char *argv[])
       use_abi_namespace = 1;
       break;
     case WIN32_OPTION:
-      do_win32 = 1;
-      do_win64 = 0;
+      pointer_size = 4;
       break;
     case WIN64_OPTION:
-      do_win32 = 0;
-      do_win64 = 1;
+      pointer_size = 8;
       break;
     case WIN32_ALIGN_OPTION:
       win32_packing = strtol(optarg, NULL, 0);
@@ -664,8 +674,8 @@ int main(int argc,char *argv[])
       wpp_add_include_path(optarg);
       break;
     case 'm':
-      if (!strcmp( optarg, "32" )) typelib_kind = SYS_WIN32;
-      else if (!strcmp( optarg, "64" )) typelib_kind = SYS_WIN64;
+      if (!strcmp( optarg, "32" )) pointer_size = 4;
+      else if (!strcmp( optarg, "64" )) pointer_size = 8;
       break;
     case 'N':
       no_preprocess = 1;
@@ -726,6 +736,7 @@ int main(int argc,char *argv[])
   }
 
 #ifdef DEFAULT_INCLUDE_DIR
+  wpp_add_include_path(DEFAULT_INCLUDE_DIR);
   char exe_path[PATH_MAX];
   get_executable_path (argv[0], &exe_path[0], sizeof (exe_path) / sizeof (exe_path[0]));
   char * rel_to_includedir = get_relative_path (DEFAULT_BINDIR, DEFAULT_INCLUDE_DIR);
@@ -739,6 +750,26 @@ int main(int argc,char *argv[])
   wpp_add_include_path(relocated_default_include_dir);
 #endif
 
+  switch (target_cpu)
+  {
+  case CPU_x86:
+      if (pointer_size == 8) target_cpu = CPU_x86_64;
+      else pointer_size = 4;
+      break;
+  case CPU_x86_64:
+      if (pointer_size == 4) target_cpu = CPU_x86;
+      else pointer_size = 8;
+      break;
+  case CPU_ARM64:
+      if (pointer_size == 4) error( "Cannot build 32-bit code for this CPU\n" );
+      pointer_size = 8;
+      break;
+  default:
+      if (pointer_size == 8) error( "Cannot build 64-bit code for this CPU\n" );
+      pointer_size = 4;
+      break;
+  }
+
   /* if nothing specified, try to guess output type from the output file name */
   if (output_name && do_everything && !do_header && !do_typelib && !do_proxies &&
       !do_client && !do_server && !do_regscript && !do_idfile && !do_dlldata)
diff --git a/mingw-w64-tools/widl/src/widl.h b/mingw-w64-tools/widl/src/widl.h
index 118e2245..4f4252e3 100644
--- a/mingw-w64-tools/widl/src/widl.h
+++ b/mingw-w64-tools/widl/src/widl.h
@@ -45,8 +45,6 @@ extern int do_regscript;
 extern int do_idfile;
 extern int do_dlldata;
 extern int old_names;
-extern int do_win32;
-extern int do_win64;
 extern int win32_packing;
 extern int win64_packing;
 extern int winrt_mode;
@@ -76,6 +74,13 @@ extern time_t now;
 extern int line_number;
 extern int char_number;
 
+enum target_cpu
+{
+    CPU_x86, CPU_x86_64, CPU_POWERPC, CPU_ARM, CPU_ARM64, CPU_LAST = CPU_ARM64
+};
+
+extern enum target_cpu target_cpu;
+
 enum stub_mode
 {
     MODE_Os,  /* inline stubs */
diff --git a/mingw-w64-tools/widl/src/widltypes.h b/mingw-w64-tools/widl/src/widltypes.h
index 08584de5..cd71e9af 100644
--- a/mingw-w64-tools/widl/src/widltypes.h
+++ b/mingw-w64-tools/widl/src/widltypes.h
@@ -40,6 +40,7 @@ typedef struct _attr_t attr_t;
 typedef struct _expr_t expr_t;
 typedef struct _type_t type_t;
 typedef struct _var_t var_t;
+typedef struct _decl_spec_t decl_spec_t;
 typedef struct _declarator_t declarator_t;
 typedef struct _ifref_t ifref_t;
 typedef struct _typelib_entry_t typelib_entry_t;
@@ -80,7 +81,6 @@ enum attr_type
     ATTR_CASE,
     ATTR_CODE,
     ATTR_COMMSTATUS,
-    ATTR_CONST, /* const pseudo-attribute */
     ATTR_CONTEXTHANDLE,
     ATTR_CONTROL,
     ATTR_DECODE,
@@ -115,7 +115,6 @@ enum attr_type
     ATTR_IMMEDIATEBIND,
     ATTR_IMPLICIT_HANDLE,
     ATTR_IN,
-    ATTR_INLINE,
     ATTR_INPUTSYNC,
     ATTR_LENGTHIS,
     ATTR_LIBLCID,
@@ -234,6 +233,18 @@ enum storage_class
     STG_REGISTER,
 };
 
+enum type_qualifier
+{
+    TYPE_QUALIFIER_NONE = 0,
+    TYPE_QUALIFIER_CONST = 1,
+};
+
+enum function_specifier
+{
+    FUNCTION_SPECIFIER_NONE,
+    FUNCTION_SPECIFIER_INLINE,
+};
+
 enum statement_type
 {
     STMT_LIBRARY,
@@ -293,6 +304,14 @@ struct str_list_entry_t
     struct list entry;
 };
 
+struct _decl_spec_t
+{
+  type_t *type;
+  enum storage_class stgclass;
+  enum type_qualifier typequalifier;
+  enum function_specifier funcspecifier;
+};
+
 struct _attr_t {
   enum attr_type type;
   union {
@@ -356,7 +375,7 @@ struct array_details
 {
   expr_t *size_is;
   expr_t *length_is;
-  struct _type_t *elem;
+  struct _decl_spec_t elem;
   unsigned int dim;
   unsigned char ptr_def_fc;
   unsigned char declptr; /* if declared as a pointer */
@@ -376,7 +395,7 @@ struct basic_details
 
 struct pointer_details
 {
-  struct _type_t *ref;
+  struct _decl_spec_t ref;
   unsigned char def_fc;
 };
 
@@ -386,6 +405,11 @@ struct bitfield_details
   const expr_t *bits;
 };
 
+struct alias_details
+{
+  struct _decl_spec_t aliasee;
+};
+
 #define HASHMAX 64
 
 struct namespace {
@@ -414,26 +438,28 @@ enum type_type
     TYPE_BITFIELD,
 };
 
+typedef union _details_t
+{
+  struct struct_details *structure;
+  struct enumeration_details *enumeration;
+  struct func_details *function;
+  struct iface_details *iface;
+  struct module_details *module;
+  struct array_details array;
+  struct coclass_details coclass;
+  struct basic_details basic;
+  struct pointer_details pointer;
+  struct bitfield_details bitfield;
+  struct alias_details alias;
+} details_t;
+
 struct _type_t {
   const char *name;
   struct namespace *namespace;
   enum type_type type_type;
   attr_list_t *attrs;
-  union
-  {
-    struct struct_details *structure;
-    struct enumeration_details *enumeration;
-    struct func_details *function;
-    struct iface_details *iface;
-    struct module_details *module;
-    struct array_details array;
-    struct coclass_details coclass;
-    struct basic_details basic;
-    struct pointer_details pointer;
-    struct bitfield_details bitfield;
-  } details;
+  details_t details;
   const char *c_name;
-  type_t *orig;                   /* dup'd types */
   unsigned int typestring_offset;
   unsigned int ptrdesc;           /* used for complex structs */
   int typelib_idx;
@@ -449,14 +475,20 @@ struct _type_t {
 
 struct _var_t {
   char *name;
-  type_t *type;
+  decl_spec_t declspec;
   attr_list_t *attrs;
   expr_t *eval;
-  enum storage_class stgclass;
   unsigned int procstring_offset;
   unsigned int typestring_offset;
 
   struct _loc_info_t loc_info;
+  /* this flag indicates that this var's type (or pointed to type in the case of
+   * array or pointer) was not fully defined at the time of declaration.
+   * If this flag is set to TRUE then the type definition will not be written for this var
+   * If this flag is set to FALSE then the type definition will only be written if it has not
+   * been written yet (determined by the type_t's 'written' flag)
+   */
+  int declonly : 1;
 
   /* parser-internal */
   struct list entry;
@@ -464,7 +496,7 @@ struct _var_t {
 
 struct _declarator_t {
   var_t *var;
-  type_t *type;
+  decl_spec_t declspec;
   type_t *func_type;
   expr_t *bits;
 
@@ -497,6 +529,7 @@ struct _importinfo_t {
 };
 
 struct _importlib_t {
+    int offset;
     char *name;
 
     int version;
@@ -539,6 +572,13 @@ struct _statement_t {
         typelib_t *lib;
         type_list_t *type_list;
     } u;
+  /* this flag indicates that this statement's type (or pointed to type in the case of
+   * array or pointer) was not fully defined at the time of declaration.
+   * If this flag is set to TRUE then the type definition will not be written for this statement
+   * If this flag is set to FALSE then the type definition will only be written if it has not
+   * been written yet (determined by the type_t's 'written' flag)
+   */
+    int declonly : 1;
 };
 
 struct _warning_t {
@@ -553,11 +593,10 @@ typedef enum {
     SYS_WIN64
 } syskind_t;
 
-extern syskind_t typelib_kind;
 extern user_type_list_t user_type_list;
 extern context_handle_list_t context_handle_list;
 extern generic_handle_list_t generic_handle_list;
-void check_for_additional_prototype_types(const var_list_t *list);
+void check_for_additional_prototype_types(type_t *type);
 
 void init_types(void);
 type_t *alloc_type(void);
@@ -582,38 +621,18 @@ void init_loc_info(loc_info_t *);
 
 char *format_namespace(struct namespace *namespace, const char *prefix, const char *separator, const char *suffix);
 
-static inline var_list_t *type_get_function_args(const type_t *func_type)
-{
-  return func_type->details.function->args;
-}
-
-static inline enum type_type type_get_type_detect_alias(const type_t *type)
-{
-    if (type->is_alias)
-        return TYPE_ALIAS;
-    return type->type_type;
-}
-
-#define STATEMENTS_FOR_EACH_FUNC(stmt, stmts) \
-  if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, statement_t, entry ) \
-    if (stmt->type == STMT_DECLARATION && stmt->u.var->stgclass == STG_NONE && \
-        type_get_type_detect_alias(stmt->u.var->type) == TYPE_FUNCTION)
-
-static inline int statements_has_func(const statement_list_t *stmts)
+static inline int is_global_namespace(const struct namespace *namespace)
 {
-  const statement_t *stmt;
-  int has_func = 0;
-  STATEMENTS_FOR_EACH_FUNC(stmt, stmts)
-  {
-    has_func = 1;
-    break;
-  }
-  return has_func;
+    return !namespace->name;
 }
 
-static inline int is_global_namespace(const struct namespace *namespace)
+static inline decl_spec_t *init_declspec(decl_spec_t *declspec, type_t *type)
 {
-    return !namespace->name;
+  declspec->type = type;
+  declspec->stgclass = STG_NONE;
+  declspec->typequalifier=TYPE_QUALIFIER_NONE;
+  declspec->funcspecifier=FUNCTION_SPECIFIER_NONE;
+  return declspec;
 }
 
 #endif
diff --git a/mingw-w64-tools/widl/src/write_msft.c b/mingw-w64-tools/widl/src/write_msft.c
index 88a80d12..da7ce89d 100644
--- a/mingw-w64-tools/widl/src/write_msft.c
+++ b/mingw-w64-tools/widl/src/write_msft.c
@@ -702,15 +702,15 @@ static void alloc_importinfo(msft_typelib_t *typelib, importinfo_t *importinfo)
 
         guid_idx = ctl2_alloc_guid(typelib, &guid);
 
-        alloc_importfile(typelib, guid_idx, importlib->version&0xffff,
-                         importlib->version>>16, importlib->name);
+        importlib->offset = alloc_importfile(typelib, guid_idx, importlib->version & 0xffff,
+                importlib->version >> 16, importlib->name);
     }
 
     if(importinfo->offset == -1 || !(importinfo->flags & MSFT_IMPINFO_OFFSET_IS_GUID)) {
         MSFT_ImpInfo impinfo;
 
         impinfo.flags = importinfo->flags;
-        impinfo.oImpFile = 0;
+        impinfo.oImpFile = importlib->offset;
 
         if(importinfo->flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
             MSFT_GuidEntry guid;
@@ -763,7 +763,7 @@ static void add_enum_typeinfo(msft_typelib_t *typelib, type_t *enumeration);
 static void add_union_typeinfo(msft_typelib_t *typelib, type_t *tunion);
 static void add_coclass_typeinfo(msft_typelib_t *typelib, type_t *cls);
 static void add_dispinterface_typeinfo(msft_typelib_t *typelib, type_t *dispinterface);
-
+static void add_typedef_typeinfo(msft_typelib_t *typelib, type_t *tdef);
 
 /****************************************************************************
  *	encode_type
@@ -862,8 +862,8 @@ static int encode_type(
     case VT_PTR:
       {
         int next_vt;
-        for(next_vt = 0; is_ptr(type); type = type_pointer_get_ref(type)) {
-            next_vt = get_type_vt(type_pointer_get_ref(type));
+        for(next_vt = 0; is_ptr(type); type = type_pointer_get_ref_type(type)) {
+            next_vt = get_type_vt(type_pointer_get_ref_type(type));
             if (next_vt != 0)
                 break;
         }
@@ -871,7 +871,7 @@ static int encode_type(
         if (next_vt == 0)
             next_vt = VT_VOID;
 
-        encode_type(typelib, next_vt, type_pointer_get_ref(type),
+        encode_type(typelib, next_vt, type_pointer_get_ref_type(type),
                     &target_type, &child_size);
         /* these types already have an implicit pointer, so we don't need to
          * add another */
@@ -912,10 +912,10 @@ static int encode_type(
 
     case VT_SAFEARRAY:
 	{
-	type_t *element_type = type_alias_get_aliasee(type_array_get_element(type));
+	type_t *element_type = type_alias_get_aliasee_type(type_array_get_element_type(type));
 	int next_vt = get_type_vt(element_type);
 
-	encode_type(typelib, next_vt, type_alias_get_aliasee(type_array_get_element(type)),
+	encode_type(typelib, next_vt, type_alias_get_aliasee_type(type_array_get_element_type(type)),
         &target_type, &child_size);
 
 	for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
@@ -966,33 +966,61 @@ static int encode_type(
         }
         else
         {
-            /* typedef'd types without public attribute aren't included in the typelib */
-            while (type_is_alias(type) && !is_attr(type->attrs, ATTR_PUBLIC))
-                type = type_alias_get_aliasee(type);
+            /* typedef'd types without public attribute aren't included in the typelib
+             * typedef'd types with a wire_marshal attribute must be included
+             */
+            while (type_is_alias(type))
+            {
+                if (is_attr(type->attrs, ATTR_WIREMARSHAL))
+                {
+                    type = get_attrp(type->attrs, ATTR_WIREMARSHAL);
+                    break;
+                }
+                else if(!is_attr(type->attrs, ATTR_PUBLIC))
+                {
+                    type = type_alias_get_aliasee_type(type);
+                }
+                else
+                {
+                    break;
+                }
+            }
 
             chat("encode_type: VT_USERDEFINED - adding new type %s, real type %d\n",
                  type->name, type_get_type(type));
 
-            switch (type_get_type(type))
+            /* we've either fully resolved the typedef down to an actual type or
+             * we must include the typedef because it's a wiremarshal (or public) type
+             */
+            if (type_is_alias(type))
             {
-            case TYPE_STRUCT:
-                add_structure_typeinfo(typelib, type);
-                break;
-            case TYPE_INTERFACE:
-                add_interface_typeinfo(typelib, type);
-                break;
-            case TYPE_ENUM:
-                add_enum_typeinfo(typelib, type);
-                break;
-            case TYPE_UNION:
-                add_union_typeinfo(typelib, type);
-                break;
-            case TYPE_COCLASS:
-                add_coclass_typeinfo(typelib, type);
-                break;
-            default:
-                error("encode_type: VT_USERDEFINED - unhandled type %d\n",
-                      type_get_type(type));
+                add_typedef_typeinfo(typelib, type);
+            }
+            else
+            {
+                switch (type_get_type(type))
+                {
+                case TYPE_STRUCT:
+                    add_structure_typeinfo(typelib, type);
+                    break;
+                case TYPE_INTERFACE:
+                    add_interface_typeinfo(typelib, type);
+                    break;
+                case TYPE_ENUM:
+                    add_enum_typeinfo(typelib, type);
+                    break;
+                /* fallthrough */
+                case TYPE_UNION:
+                case TYPE_ENCAPSULATED_UNION:
+                    add_union_typeinfo(typelib, type);
+                    break;
+                case TYPE_COCLASS:
+                    add_coclass_typeinfo(typelib, type);
+                    break;
+                default:
+                    error("encode_type: VT_USERDEFINED - unhandled type %d\n",
+                          type_get_type(type));
+                }
             }
 
             typeinfo_offset = typelib->typelib_typeinfo_offsets[type->typelib_idx];
@@ -1056,7 +1084,7 @@ static int encode_var(
         num_dims = 0;
         for (atype = type;
              is_array(atype) && !type_array_is_decl_as_ptr(atype);
-             atype = type_array_get_element(atype))
+             atype = type_array_get_element_type(atype))
             ++num_dims;
 
         chat("array with %d dimensions\n", num_dims);
@@ -1071,7 +1099,7 @@ static int encode_var(
         arraydata += 2;
         for (atype = type;
              is_array(atype) && !type_array_is_decl_as_ptr(atype);
-             atype = type_array_get_element(atype))
+             atype = type_array_get_element_type(atype))
         {
             arraydata[0] = type_array_get_dim(atype);
             arraydata[1] = 0;
@@ -1093,7 +1121,7 @@ static int encode_var(
     vt = get_type_vt(type);
     if (vt == VT_PTR) {
         type_t *ref = is_ptr(type) ?
-            type_pointer_get_ref(type) : type_array_get_element(type);
+            type_pointer_get_ref_type(type) : type_array_get_element_type(type);
         int skip_ptr = encode_var(typelib, ref, var, &target_type, &child_size);
 
         if(skip_ptr == 2) {
@@ -1114,7 +1142,7 @@ static int encode_var(
 	    if (target_type & 0x80000000) {
 		mix_field = ((target_type >> 16) & 0x3fff) | VT_BYREF;
 	    } else if (get_type_vt(ref) == VT_SAFEARRAY) {
-		type_t *element_type = type_alias_get_aliasee(type_array_get_element(ref));
+		type_t *element_type = type_alias_get_aliasee_type(type_array_get_element_type(ref));
 		mix_field = get_type_vt(element_type) | VT_ARRAY | VT_BYREF;
 	    } else {
 		typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
@@ -1204,7 +1232,7 @@ static void write_default_value(msft_typelib_t *typelib, type_t *type, expr_t *e
     if (type_get_type(type) == TYPE_ENUM) {
         vt = VT_I4;
     } else if (is_ptr(type)) {
-        vt = get_type_vt(type_pointer_get_ref(type));
+        vt = get_type_vt(type_pointer_get_ref_type(type));
         if (vt == VT_USERDEFINED)
             vt = VT_I4;
         if (expr->cval)
@@ -1301,8 +1329,8 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index)
         return S_FALSE;
     }
 
-    if (type_get_function_args(func->type))
-      LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), var_t, entry )
+    if (type_function_get_args(func->declspec.type))
+      LIST_FOR_EACH_ENTRY( arg, type_function_get_args(func->declspec.type), var_t, entry )
       {
         num_params++;
         if (arg->attrs) LIST_FOR_EACH_ENTRY( attr, arg->attrs, const attr_t, entry ) {
@@ -1444,7 +1472,7 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index)
 
     /* fill out the basic type information */
     typedata[0] = typedata_size | (index << 16);
-    encode_var(typeinfo->typelib, type_function_get_rettype(func->type), func,
+    encode_var(typeinfo->typelib, type_function_get_rettype(func->declspec.type), func,
         &typedata[1], &decoded_size);
     typedata[2] = funcflags;
     typedata[3] = ((52 /*sizeof(FUNCDESC)*/ + decoded_size) << 16) | typeinfo->typeinfo->cbSizeVft;
@@ -1471,10 +1499,10 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index)
         warning("unknown number of optional attrs\n");
     }
 
-    if (type_get_function_args(func->type))
+    if (type_function_get_args(func->declspec.type))
     {
       i = 0;
-      LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), var_t, entry )
+      LIST_FOR_EACH_ENTRY( arg, type_function_get_args(func->declspec.type), var_t, entry )
       {
         int paramflags = 0;
         int *paramdata = typedata + 6 + extra_attr + (num_defaults ? num_params : 0) + i * 3;
@@ -1482,13 +1510,13 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index)
 
         if(defaultdata) *defaultdata = -1;
 
-	encode_var(typeinfo->typelib, arg->type, arg, paramdata, &decoded_size);
+	    encode_var(typeinfo->typelib, arg->declspec.type, arg, paramdata, &decoded_size);
         if (arg->attrs) LIST_FOR_EACH_ENTRY( attr, arg->attrs, const attr_t, entry ) {
             switch(attr->type) {
             case ATTR_DEFAULTVALUE:
               {
                 paramflags |= 0x30; /* PARAMFLAG_FHASDEFAULT | PARAMFLAG_FOPT */
-                write_default_value(typeinfo->typelib, arg->type, (expr_t *)attr->u.pval, defaultdata);
+                write_default_value(typeinfo->typelib, arg->declspec.type, (expr_t *)attr->u.pval, defaultdata);
                 break;
               }
             case ATTR_IN:
@@ -1572,10 +1600,10 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, var_t *func, int index)
     if(typeinfo->typekind == TKIND_MODULE)
         namedata[9] |= 0x20;
 
-    if (type_get_function_args(func->type))
+    if (type_function_get_args(func->declspec.type))
     {
         i = 0;
-        LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), var_t, entry )
+        LIST_FOR_EACH_ENTRY( arg, type_function_get_args(func->declspec.type), var_t, entry )
         {
             /* don't give the last arg of a [propput*] func a name */
             if(i != num_params - 1 || (invokekind != 0x4 /* INVOKE_PROPERTYPUT */ && invokekind != 0x8 /* INVOKE_PROPERTYPUTREF */))
@@ -1697,8 +1725,8 @@ static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var)
     typeinfo->var_offsets[var_num] = offset;
 
     /* figure out type widths and whatnot */
-    var_datawidth = type_memsize_and_alignment(var->type, &var_alignment);
-    encode_var(typeinfo->typelib, var->type, var, &typedata[1], &var_type_size);
+    var_datawidth = type_memsize_and_alignment(var->declspec.type, &var_alignment);
+    encode_var(typeinfo->typelib, var->declspec.type, var, &typedata[1], &var_type_size);
 
     /* pad out starting position to data width */
     typeinfo->datawidth += var_alignment - 1;
@@ -1977,6 +2005,7 @@ static void add_dispinterface_typeinfo(msft_typelib_t *typelib, type_t *dispinte
     var_t *var;
     msft_typeinfo_t *msft_typeinfo;
 
+    assert(type_get_type_detect_alias(dispinterface) == TYPE_INTERFACE);
     if (-1 < dispinterface->typelib_idx)
         return;
 
@@ -2181,7 +2210,7 @@ static void add_typedef_typeinfo(msft_typelib_t *typelib, type_t *tdef)
     if (-1 < tdef->typelib_idx)
         return;
 
-    type = type_alias_get_aliasee(tdef);
+    type = type_alias_get_aliasee_type(tdef);
 
     if (!type->name || strcmp(tdef->name, type->name) != 0)
     {
@@ -2297,6 +2326,7 @@ static void add_module_typeinfo(msft_typelib_t *typelib, type_t *module)
     const statement_t *stmt;
     msft_typeinfo_t *msft_typeinfo;
 
+    assert(type_get_type_detect_alias(module) == TYPE_MODULE);
     if (-1 < module->typelib_idx)
         return;
 
@@ -2364,7 +2394,7 @@ static void add_entry(msft_typelib_t *typelib, const statement_t *stmt)
             if (is_attr(type_entry->type->attrs, ATTR_PUBLIC))
                 add_typedef_typeinfo(typelib, type_entry->type);
             else
-                add_type_typeinfo(typelib, type_alias_get_aliasee(type_entry->type));
+                add_type_typeinfo(typelib, type_alias_get_aliasee_type(type_entry->type));
         }
         break;
     }
@@ -2653,8 +2683,6 @@ int create_msft_typelib(typelib_t *typelib)
     GUID midl_info_guid = {0xde77ba65,0x517c,0x11d1,{0xa2,0xda,0x00,0x00,0xf8,0x77,0x3c,0xe9}};
     char info_string[128];
 
-    pointer_size = (typelib_kind == SYS_WIN64) ? 8 : 4;
-
     msft = xmalloc(sizeof(*msft));
     memset(msft, 0, sizeof(*msft));
     msft->typelib = typelib;
@@ -2662,7 +2690,7 @@ int create_msft_typelib(typelib_t *typelib)
     ctl2_init_header(msft);
     ctl2_init_segdir(msft);
 
-    msft->typelib_header.varflags |= typelib_kind;
+    msft->typelib_header.varflags |= (pointer_size == 8) ? SYS_WIN64 : SYS_WIN32;
 
     /*
      * The following two calls return an offset or -1 if out of memory. We
